mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-23 07:09:08 -04:00
Async model migrations
This commit is contained in:
1 parent
fe7781998b
commit
a20ea65c4c
13 files changed
+71
-64
No files matched your search
@@ -19,7 +19,8 @@ describe('exportHarWithRequest()', () => {
|
||||
lastAccessed: new Date('2096-10-05T04:40:49.505Z')
|
||||
}];
|
||||
|
||||
await models.cookieJar.create({
|
||||
const cookieJar = await models.cookieJar.getOrCreateForParentId(workspace._id);
|
||||
await models.cookieJar.update(cookieJar, {
|
||||
parentId: workspace._id,
|
||||
cookies
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('export()', () => {
|
||||
it('succeed with username and password', async () => {
|
||||
const w = await models.workspace.create({name: 'Workspace'});
|
||||
const r1 = await models.request.create({name: 'Request', parentId: w._id});
|
||||
const eBase = await models.environment.create({name: 'Base', parentId: w._id});
|
||||
const eBase = await models.environment.getOrCreateForWorkspace(w);
|
||||
const ePub = await models.environment.create({name: 'Public', parentId: eBase._id});
|
||||
await models.environment.create({name: 'Private', isPrivate: true, parentId: eBase._id});
|
||||
|
||||
@@ -21,8 +21,9 @@ describe('export()', () => {
|
||||
expect(data.__export_source).toBe(`insomnia.desktop.app:v${getAppVersion()}`);
|
||||
expect(data.resources[0]._id).toBe(w._id);
|
||||
expect(data.resources[1]._id).toBe(eBase._id);
|
||||
expect(data.resources[2]._id).toBe(r1._id);
|
||||
expect(data.resources[3]._id).toBe(ePub._id);
|
||||
expect(data.resources.length).toBe(4);
|
||||
expect(data.resources[2]._id).toBe('jar_dd2ccc1a2745477a881a9e8ef9d42403');
|
||||
expect(data.resources[3]._id).toBe(r1._id);
|
||||
expect(data.resources[4]._id).toBe(ePub._id);
|
||||
expect(data.resources.length).toBe(5);
|
||||
});
|
||||
});
|
||||
+18
-16
@@ -155,16 +155,17 @@ export function findMostRecentlyModified (
|
||||
limit: number | null = null
|
||||
): Promise<Array<BaseModel>> {
|
||||
return new Promise(resolve => {
|
||||
db[type].find(query).sort({modified: -1}).limit(limit).exec((err, rawDocs) => {
|
||||
db[type].find(query).sort({modified: -1}).limit(limit).exec(async (err, rawDocs) => {
|
||||
if (err) {
|
||||
console.warn('[db] Failed to find docs', err);
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const docs = rawDocs.map(rawDoc => {
|
||||
return initModel(type, rawDoc);
|
||||
});
|
||||
const docs = [];
|
||||
for (const rawDoc of rawDocs) {
|
||||
docs.push(await initModel(type, rawDoc));
|
||||
}
|
||||
|
||||
resolve(docs);
|
||||
});
|
||||
@@ -177,14 +178,15 @@ export function find<T: BaseModel> (
|
||||
sort: Object = {created: 1}
|
||||
): Promise<Array<T>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db[type].find(query).sort(sort).exec((err, rawDocs) => {
|
||||
db[type].find(query).sort(sort).exec(async (err, rawDocs) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
const docs = rawDocs.map(rawDoc => {
|
||||
return initModel(type, rawDoc);
|
||||
});
|
||||
const docs = [];
|
||||
for (const rawDoc of rawDocs) {
|
||||
docs.push(await initModel(type, rawDoc));
|
||||
}
|
||||
|
||||
resolve(docs);
|
||||
});
|
||||
@@ -231,8 +233,8 @@ export async function upsert (doc: BaseModel, fromSync: boolean = false): Promis
|
||||
}
|
||||
|
||||
export function insert<T: BaseModel> (doc: T, fromSync: boolean = false): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const docWithDefaults = initModel(doc.type, doc);
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const docWithDefaults = await initModel(doc.type, doc);
|
||||
db[doc.type].insert(docWithDefaults, (err, newDoc) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
@@ -245,8 +247,8 @@ export function insert<T: BaseModel> (doc: T, fromSync: boolean = false): Promis
|
||||
}
|
||||
|
||||
export function update<T: BaseModel> (doc: T, fromSync: boolean = false): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const docWithDefaults = initModel(doc.type, doc);
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const docWithDefaults = await initModel(doc.type, doc);
|
||||
db[doc.type].update({_id: docWithDefaults._id}, docWithDefaults, err => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
@@ -295,8 +297,8 @@ export async function removeWhere (type: string, query: Object): Promise<void> {
|
||||
// DEFAULT MODEL STUFF //
|
||||
// ~~~~~~~~~~~~~~~~~~~ //
|
||||
|
||||
export function docUpdate<T: BaseModel> (originalDoc: T, patch: Object = {}): Promise<T> {
|
||||
const doc = initModel(
|
||||
export async function docUpdate<T: BaseModel> (originalDoc: T, patch: Object = {}): Promise<T> {
|
||||
const doc = await initModel(
|
||||
originalDoc.type,
|
||||
originalDoc,
|
||||
|
||||
@@ -309,8 +311,8 @@ export function docUpdate<T: BaseModel> (originalDoc: T, patch: Object = {}): Pr
|
||||
return update(doc);
|
||||
}
|
||||
|
||||
export function docCreate<T: BaseModel> (type: string, ...patches: Array<Object>): Promise<T> {
|
||||
const doc = initModel(
|
||||
export async function docCreate<T: BaseModel> (type: string, ...patches: Array<Object>): Promise<T> {
|
||||
const doc = await initModel(
|
||||
type,
|
||||
...patches,
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ describe('migrate()', () => {
|
||||
expect(models.request.migrate(noBody)).toEqual(expected2);
|
||||
});
|
||||
|
||||
it('migrates from initModel()', () => {
|
||||
it('migrates from initModel()', async () => {
|
||||
Date.now = jest.fn().mockReturnValue(1478795580200);
|
||||
|
||||
const original = {
|
||||
@@ -283,7 +283,7 @@ describe('migrate()', () => {
|
||||
settingEncodeUrl: true
|
||||
};
|
||||
|
||||
const migrated = models.initModel(models.request.type, original);
|
||||
const migrated = await models.initModel(models.request.type, original);
|
||||
expect(migrated).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -13,7 +13,7 @@ describe('migrate()', () => {
|
||||
it('migrates utf8 body correctly', async () => {
|
||||
const initialModel = {body: 'hello world!', encoding: 'utf8'};
|
||||
|
||||
const newModel = models.initModel(models.response.type, initialModel);
|
||||
const newModel = await models.initModel(models.response.type, initialModel);
|
||||
const expectedBodyPath = path.join(
|
||||
electron.remote.app.getPath('userData'),
|
||||
`responses/fc3ff98e8c6a0d3087d515c0473f8677.zip`
|
||||
@@ -32,7 +32,7 @@ describe('migrate()', () => {
|
||||
it('migrates base64 body correctly', async () => {
|
||||
const initialModel = {body: 'aGVsbG8gd29ybGQh', encoding: 'base64'};
|
||||
|
||||
const newModel = models.initModel(models.response.type, initialModel);
|
||||
const newModel = await models.initModel(models.response.type, initialModel);
|
||||
jest.runAllTimers();
|
||||
const expectedBodyPath = path.join(
|
||||
electron.remote.app.getPath('userData'),
|
||||
@@ -52,7 +52,7 @@ describe('migrate()', () => {
|
||||
it('migrates empty body', async () => {
|
||||
const initialModel = {body: ''};
|
||||
|
||||
const newModel = models.initModel(models.response.type, initialModel);
|
||||
const newModel = await models.initModel(models.response.type, initialModel);
|
||||
jest.runAllTimers();
|
||||
jest.runAllTimers();
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('migrate()', () => {
|
||||
it('does not migrate body again', async () => {
|
||||
const initialModel = {bodyPath: '/foo/bar'};
|
||||
|
||||
const newModel = models.initModel(models.response.type, initialModel);
|
||||
const newModel = await models.initModel(models.response.type, initialModel);
|
||||
|
||||
// Should have stripped these
|
||||
expect(newModel.body).toBeUndefined();
|
||||
|
||||
@@ -33,14 +33,14 @@ export function findByParentId (parentId) {
|
||||
return db.find(type, {parentId});
|
||||
}
|
||||
|
||||
export async function getOrCreateForWorkspace (workspace) {
|
||||
export async function getOrCreateForWorkspaceId (workspaceId) {
|
||||
let environment = await db.getWhere(type, {
|
||||
parentId: workspace._id
|
||||
parentId: workspaceId
|
||||
});
|
||||
|
||||
if (!environment) {
|
||||
environment = await create({
|
||||
parentId: workspace._id,
|
||||
parentId: workspaceId,
|
||||
name: 'Base Environment'
|
||||
});
|
||||
}
|
||||
@@ -48,6 +48,10 @@ export async function getOrCreateForWorkspace (workspace) {
|
||||
return environment;
|
||||
}
|
||||
|
||||
export async function getOrCreateForWorkspace (workspace) {
|
||||
return getOrCreateForWorkspaceId(workspace._id);
|
||||
}
|
||||
|
||||
export function getById (id) {
|
||||
return db.get(type, id);
|
||||
}
|
||||
|
||||
+5
-5
@@ -82,7 +82,7 @@ export function getModelName (type: string, count: number = 1) {
|
||||
}
|
||||
}
|
||||
|
||||
export function initModel (type: string, ...sources: Array<Object>) {
|
||||
export async function initModel <T: BaseModel> (type: string, ...sources: Array<Object>): Promise<T> {
|
||||
const model = getModel(type);
|
||||
|
||||
if (!model) {
|
||||
@@ -108,14 +108,14 @@ export function initModel (type: string, ...sources: Array<Object>) {
|
||||
|
||||
// Migrate the model
|
||||
// NOTE: Do migration before pruning because we might need to look at those fields
|
||||
model.migrate(fullObject);
|
||||
const migratedDoc = await model.migrate(fullObject);
|
||||
|
||||
// Prune extra keys from doc
|
||||
for (const key of Object.keys(fullObject)) {
|
||||
for (const key of Object.keys(migratedDoc)) {
|
||||
if (!objectDefaults.hasOwnProperty(key)) {
|
||||
delete fullObject[key];
|
||||
delete migratedDoc[key];
|
||||
}
|
||||
}
|
||||
|
||||
return fullObject;
|
||||
return migratedDoc;
|
||||
}
|
||||
+7
-10
@@ -32,7 +32,7 @@ export function init () {
|
||||
};
|
||||
}
|
||||
|
||||
export function migrate (doc: Object) {
|
||||
export async function migrate (doc: Object) {
|
||||
// There was a bug on import that would set this to the current workspace ID.
|
||||
// Let's remove it here so that nothing bad happens.
|
||||
if (doc.parentId !== null) {
|
||||
@@ -40,6 +40,10 @@ export function migrate (doc: Object) {
|
||||
process.nextTick(() => update(doc, {parentId: null}));
|
||||
}
|
||||
|
||||
// Ensure child dependencies exist
|
||||
await models.cookieJar.getOrCreateForParentId(doc._id);
|
||||
await models.environment.getOrCreateForWorkspaceId(doc._id);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -47,15 +51,8 @@ export function getById (id: string): Promise<Workspace | null> {
|
||||
return db.get(type, id);
|
||||
}
|
||||
|
||||
export async function create (patch: Object = {}): Promise<Workspace> {
|
||||
const workspace = await db.docCreate(type, patch);
|
||||
|
||||
// Make sure CookieJars and environments exist for all workspaces
|
||||
// TODO: Find a better place to do this
|
||||
await models.cookieJar.getOrCreateForParentId(workspace._id);
|
||||
await models.environment.getOrCreateForWorkspace(workspace);
|
||||
|
||||
return workspace;
|
||||
export function create (patch: Object = {}): Promise<Workspace> {
|
||||
return db.docCreate(type, patch);
|
||||
}
|
||||
|
||||
export async function all (): Promise<Array<Workspace>> {
|
||||
|
||||
@@ -31,7 +31,8 @@ describe('actuallySend()', () => {
|
||||
lastAccessed: new Date('2096-10-05T04:40:49.505Z')
|
||||
}];
|
||||
|
||||
await models.cookieJar.create({
|
||||
const cookieJar = await models.cookieJar.getOrCreateForParentId(workspace._id);
|
||||
await models.cookieJar.update(cookieJar, {
|
||||
parentId: workspace._id,
|
||||
cookies
|
||||
});
|
||||
|
||||
@@ -248,8 +248,6 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
await models.request.create({_id: 'req_1', name: 'Request 1', parentId: 'wrk_1'});
|
||||
await models.request.create({_id: 'req_2', name: 'Request 2', parentId: 'wrk_1'});
|
||||
await models.request.create({_id: 'req_3', name: 'Request 3', parentId: 'wrk_1'});
|
||||
await models.cookieJar.create({_id: 'jar_1', name: 'Jar 1', parentId: 'wrk_1'});
|
||||
await models.environment.create({_id: 'env_1', name: 'Env 1', parentId: 'wrk_1'});
|
||||
await models.environment.create({_id: 'env_2', name: 'Env Prv', parentId: 'wrk_1', isPrivate: true});
|
||||
|
||||
// Flush changes just to be sure they won't affect our tests
|
||||
@@ -259,8 +257,8 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
// Assert that all our new models were created
|
||||
expect((await models.workspace.all()).length).toBe(2);
|
||||
expect((await models.request.all()).length).toBe(3);
|
||||
expect((await models.environment.all()).length).toBe(2);
|
||||
expect((await models.cookieJar.all()).length).toBe(1);
|
||||
expect((await models.environment.all()).length).toBe(3);
|
||||
expect((await models.cookieJar.all()).length).toBe(2);
|
||||
|
||||
// Assert that initializing sync will create the initial resources
|
||||
expect((await syncStorage.allConfigs()).length).toBe(0);
|
||||
@@ -269,7 +267,7 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
jest.runOnlyPendingTimers();
|
||||
await promise;
|
||||
expect((await syncStorage.allConfigs()).length).toBe(2);
|
||||
expect((await syncStorage.allResources()).length).toBe(7);
|
||||
expect((await syncStorage.allResources()).length).toBe(9);
|
||||
|
||||
// Mark all configs as auto sync
|
||||
const configs = await syncStorage.allConfigs();
|
||||
@@ -304,12 +302,12 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
|
||||
// Assert
|
||||
expect((await syncStorage.allConfigs()).length).toBe(2);
|
||||
expect((await syncStorage.allResources()).length).toBe(8);
|
||||
expect((await syncStorage.allResources()).length).toBe(10);
|
||||
expect(_decryptResource(resource).url).toBe('https://google.com');
|
||||
expect(resource.removed).toBe(false);
|
||||
|
||||
expect(session.syncPush.mock.calls.length).toBe(1);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(8);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(10);
|
||||
|
||||
expect(session.syncPull.mock.calls).toEqual([]);
|
||||
});
|
||||
@@ -368,7 +366,7 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
expect(resource.removed).toBe(false);
|
||||
|
||||
expect(session.syncPush.mock.calls.length).toBe(1);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(7);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(9);
|
||||
|
||||
expect(session.syncPull.mock.calls).toEqual([]);
|
||||
});
|
||||
@@ -391,7 +389,7 @@ describe('Integration tests for creating Resources and pushing', () => {
|
||||
expect(updatedResource.removed).toBe(true);
|
||||
|
||||
expect(session.syncPush.mock.calls.length).toBe(1);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(7);
|
||||
expect(session.syncPush.mock.calls[0][0].length).toBe(9);
|
||||
|
||||
expect(session.syncPull.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
import type {Request} from '../../../../models/request';
|
||||
import classnames from 'classnames';
|
||||
import {newBodyRaw} from '../../../../models/request';
|
||||
import React from 'react';
|
||||
import autobind from 'autobind-decorator';
|
||||
@@ -228,7 +229,7 @@ class GraphQLEditor extends React.PureComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="txt-sm super-faint italic pad-sm inline-block">
|
||||
<div className="txt-sm super-faint italic pad-sm no-pad-right inline-block">
|
||||
{message}
|
||||
</div>
|
||||
);
|
||||
@@ -251,7 +252,8 @@ class GraphQLEditor extends React.PureComponent {
|
||||
schemaFetchError,
|
||||
hideSchemaFetchErrors,
|
||||
variablesSyntaxError,
|
||||
forceRefreshKey
|
||||
forceRefreshKey,
|
||||
schemaIsFetching
|
||||
} = this.state;
|
||||
|
||||
const {
|
||||
@@ -294,13 +296,10 @@ class GraphQLEditor extends React.PureComponent {
|
||||
)}
|
||||
</div>
|
||||
<div className="graphql-editor__schema-notice">
|
||||
<button
|
||||
className="icon pad-left-sm pad-top-sm pad-bottom-sm"
|
||||
onClick={this._handleRefreshSchema}
|
||||
>
|
||||
<i className="fa fa-refresh" />
|
||||
</button>
|
||||
{this.renderSchemaFetchMessage()}
|
||||
<button className={classnames('icon space-left', {'fa-spin': schemaIsFetching})} onClick={this._handleRefreshSchema}>
|
||||
<i className="fa fa-refresh"/>
|
||||
</button>
|
||||
</div>
|
||||
<h2 className="no-margin pad-left-sm pad-top-sm pad-bottom-sm">
|
||||
Query Variables <HelpTooltip>Variables to use in GraphQL query <br/>(JSON
|
||||
|
||||
@@ -37,7 +37,7 @@ class RequestCreateModal extends PureComponent {
|
||||
e.preventDefault();
|
||||
|
||||
const {parentId, selectedContentType, selectedMethod} = this.state;
|
||||
const request = models.initModel(models.request.type, {
|
||||
const request = await models.initModel(models.request.type, {
|
||||
parentId,
|
||||
name: this._input.value,
|
||||
method: selectedMethod
|
||||
|
||||
@@ -526,6 +526,10 @@ i.fa:not(.fa--skinny) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.no-pad-right {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.no-pad-left {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user