Skip to content
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

move storage classes to toolkit #2412

Merged
merged 3 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/curvy-news-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': minor
'@graphiql/toolkit': minor
---

Move QueryStore from `graphiql` package to `@graphiql/toolkit`
6 changes: 6 additions & 0 deletions .changeset/friendly-cougars-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': minor
'@graphiql/toolkit': minor
---

Move HistoryStore from `graphiql` package to `@graphiql/toolkit`
6 changes: 6 additions & 0 deletions .changeset/strong-olives-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': minor
'@graphiql/toolkit': minor
---

Move StorageAPI from `graphiql` package to `@graphiql/toolkit`
1 change: 1 addition & 0 deletions packages/graphiql-toolkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './async-helpers';
export * from './create-fetcher';
export * from './format';
export * from './storage';
// TODO: move the most useful utilities from graphiql to here
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import StorageAPI from '../StorageAPI';
import { StorageAPI } from '../base';

describe('StorageAPI', () => {
const storage = new StorageAPI();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import QueryStore from '../QueryStore';
import StorageAPI from '../StorageAPI';
import { StorageAPI } from '../base';
import { QueryStore } from '../query';

class StorageMock {
shouldThrow: () => boolean;
Expand All @@ -23,9 +16,8 @@ class StorageMock {

if (this.shouldThrow()) {
return {
error: {},
error: new Error('boom'),
isQuotaError: true,
storageAvailable: true,
};
}

Expand All @@ -34,7 +26,6 @@ class StorageMock {
return {
error: null,
isQuotaError: false,
storageAvailable: true,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

export interface Storage {
getItem: (key: string) => string | null;
removeItem: (key: string) => void;
setItem: (key: string, value: string) => void;
export type Storage = {
getItem(key: string): string | null;
removeItem(key: string): void;
setItem(key: string, value: string): void;
length: number;
}
};

function isQuotaError(storage: Storage, e: Error) {
function isQuotaError(storage: Storage, e: unknown) {
return (
e instanceof DOMException &&
// everything except Firefox
Expand All @@ -29,7 +22,7 @@ function isQuotaError(storage: Storage, e: Error) {
);
}

export default class StorageAPI {
export class StorageAPI {
storage: Storage | null;

constructor(storage?: Storage) {
Expand All @@ -38,32 +31,35 @@ export default class StorageAPI {
}

get(name: string): string | null {
if (this.storage) {
const value = this.storage.getItem('graphiql:' + name);
// Clean up any inadvertently saved null/undefined values.
if (value === 'null' || value === 'undefined') {
this.storage.removeItem('graphiql:' + name);
return null;
}
if (!this.storage) {
return null;
}

if (value) {
return value;
}
const key = `${STORAGE_NAMESPACE}:${name}`;
const value = this.storage.getItem(key);
// Clean up any inadvertently saved null/undefined values.
if (value === 'null' || value === 'undefined') {
this.storage.removeItem(key);
return null;
}
return null;

return value || null;
}

set(name: string, value: string) {
set(
name: string,
value: string,
): { isQuotaError: boolean; error: Error | null } {
let quotaError = false;
let error = null;
let error: Error | null = null;

if (this.storage) {
const key = `graphiql:${name}`;
const key = `${STORAGE_NAMESPACE}:${name}`;
if (value) {
try {
this.storage.setItem(key, value);
} catch (e) {
error = e;
error = e instanceof Error ? e : new Error(`${e}`);
quotaError = isQuotaError(this.storage, e);
}
} else {
Expand All @@ -72,9 +68,8 @@ export default class StorageAPI {
}
}

return {
isQuotaError: quotaError,
error,
};
return { isQuotaError: quotaError, error };
}
}

const STORAGE_NAMESPACE = 'graphiql';
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import QueryStore, { QueryStoreItem } from './QueryStore';
import StorageAPI from './StorageAPI';
import { parse } from 'graphql';
import {
HandleEditLabelFn,
HandleToggleFavoriteFn,
} from '../components/HistoryQuery';

import { StorageAPI } from './base';
import { QueryStore, QueryStoreItem } from './query';

const MAX_QUERY_SIZE = 100000;

export default class HistoryStore {
export class HistoryStore {
queries: Array<QueryStoreItem>;
history: QueryStore;
favorite: QueryStore;
Expand All @@ -27,15 +18,16 @@ export default class HistoryStore {
);
// favorites are not automatically deleted, so there's no need for a max length
this.favorite = new QueryStore('favorites', this.storage, null);
this.queries = this.fetchAllQueries();

this.queries = [...this.history.fetchAll(), ...this.favorite.fetchAll()];
}

shouldSaveQuery = (
private shouldSaveQuery(
query?: string,
variables?: string,
headers?: string,
lastQuerySaved?: QueryStoreItem,
) => {
) {
if (!query) {
return false;
}
Expand Down Expand Up @@ -71,15 +63,8 @@ export default class HistoryStore {
}
}
return true;
};

fetchAllQueries = () => {
const historyQueries = this.history.fetchAll();
const favoriteQueries = this.favorite.fetchAll();
return historyQueries.concat(favoriteQueries);
};
}

// Public API
updateHistory = (
query?: string,
variables?: string,
Expand All @@ -106,15 +91,14 @@ export default class HistoryStore {
}
};

// Public API
toggleFavorite: HandleToggleFavoriteFn = (
query,
variables,
headers,
operationName,
label,
favorite,
) => {
toggleFavorite(
query?: string,
variables?: string,
headers?: string,
operationName?: string,
label?: string,
favorite?: boolean,
) {
const item: QueryStoreItem = {
query,
variables,
Expand All @@ -130,17 +114,16 @@ export default class HistoryStore {
this.favorite.delete(item);
}
this.queries = [...this.history.items, ...this.favorite.items];
};
}

// Public API
editLabel: HandleEditLabelFn = (
query,
variables,
headers,
operationName,
label,
favorite,
) => {
editLabel(
query?: string,
variables?: string,
headers?: string,
operationName?: string,
label?: string,
favorite?: boolean,
) {
const item = {
query,
variables,
Expand All @@ -154,5 +137,5 @@ export default class HistoryStore {
this.history.edit(item);
}
this.queries = [...this.history.items, ...this.favorite.items];
};
}
}
3 changes: 3 additions & 0 deletions packages/graphiql-toolkit/src/storage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './base';
export * from './history';
export * from './query';
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import StorageAPI from './StorageAPI';
import { StorageAPI } from './base';

export type QueryStoreItem = {
query?: string;
Expand All @@ -15,7 +9,7 @@ export type QueryStoreItem = {
favorite?: boolean;
};

export default class QueryStore {
export class QueryStore {
items: Array<QueryStoreItem>;

constructor(
Expand Down
12 changes: 6 additions & 6 deletions packages/graphiql/src/components/GraphiQL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import { HeaderEditor } from './HeaderEditor';
import { ResultViewer, RESULT_VIEWER_ID } from './ResultViewer';
import { DocExplorer } from './DocExplorer';
import { QueryHistory } from './QueryHistory';
import StorageAPI, { Storage } from '../utility/StorageAPI';
import getSelectedOperationName from '../utility/getSelectedOperationName';
import debounce from '../utility/debounce';
import find from '../utility/find';
Expand All @@ -71,19 +70,20 @@ import {
fetcherReturnToPromise,
formatError,
formatResult,
isPromise,
isObservable,
HistoryStore,
isAsyncIterable,
isObservable,
isPromise,
StorageAPI,
} from '@graphiql/toolkit';
import type {
Fetcher,
FetcherResult,
FetcherOpts,
FetcherResult,
FetcherResultPayload,
SyncFetcherResult,
Unsubscribable,
FetcherResultPayload,
} from '@graphiql/toolkit';
import HistoryStore from '../utility/HistoryStore';

import { validateSchema } from 'graphql';
import { Tab, TabAddButton, Tabs } from './Tabs';
Expand Down
2 changes: 1 addition & 1 deletion packages/graphiql/src/components/HistoryQuery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { QueryStoreItem } from '../utility/QueryStore';
import type { QueryStoreItem } from '@graphiql/toolkit';

export type HandleEditLabelFn = (
query?: string,
Expand Down
5 changes: 2 additions & 3 deletions packages/graphiql/src/components/QueryHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
* LICENSE file in the root directory of this source tree.
*/

import { HistoryStore, QueryStoreItem, StorageAPI } from '@graphiql/toolkit';
import React, { ReactNode } from 'react';
import { QueryStoreItem } from '../utility/QueryStore';

import HistoryQuery, {
HandleEditLabelFn,
HandleSelectQueryFn,
HandleToggleFavoriteFn,
} from './HistoryQuery';
import StorageAPI from '../utility/StorageAPI';
import HistoryStore from '../utility/HistoryStore';

type QueryHistoryProps = {
onSelectQuery: HandleSelectQueryFn;
Expand Down
4 changes: 2 additions & 2 deletions packages/graphiql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ export type {
FetcherParams,
FetcherResult,
FetcherReturnType,
SyncFetcherResult,
Observable,
Storage,
SyncFetcherResult,
} from '@graphiql/toolkit';
/**
* Components
Expand All @@ -49,7 +50,6 @@ export { ToolbarSelect, ToolbarSelectOption } from './components/ToolbarSelect';
export { fillLeafs } from './utility/fillLeafs';
export { default as mergeAst } from './utility/mergeAst';
export { default as getSelectedOperationName } from './utility/getSelectedOperationName';
export { Storage } from './utility/StorageAPI';

/**
* Legacy exports
Expand Down