Skip to content

Commit 46d8a61

Browse files
Enable strict null check for overmind (codesandbox#3423)
* Enable strict null check for overmind * Updates * Fix one more! * typing fixes * type fixes * Convert live * Convert client * Add support for @babel/plugin-proposal-nullish-coalescing-operator in app * Clean up yarn.lock * Fix src/app/overmind/effects/git/export-to-github.ts * Fix the loading of sandboxes * more null check handling * Fix type of color * Fix typing of module id * Change some typechecks on currentModule * Fix now check * Fix check for user.id * Handle forking errors more gracefully Co-authored-by: Christian Alfoni <[email protected]>
1 parent d91170b commit 46d8a61

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1181
-570
lines changed

packages/app/config/babel.dev.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module.exports = {
3333
require.resolve('@babel/plugin-proposal-object-rest-spread'),
3434
require.resolve('@babel/plugin-proposal-class-properties'),
3535
require.resolve('@babel/plugin-proposal-optional-chaining'),
36+
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
3637
require.resolve('@babel/plugin-transform-runtime'),
3738
require.resolve('babel-plugin-lodash'),
3839
require.resolve('@babel/plugin-syntax-dynamic-import'),

packages/app/config/babel.prod.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
require.resolve('@babel/plugin-proposal-object-rest-spread'),
3232
require.resolve('@babel/plugin-proposal-class-properties'),
3333
require.resolve('@babel/plugin-proposal-optional-chaining'),
34+
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
3435
require.resolve('@babel/plugin-transform-runtime'),
3536
require.resolve('babel-plugin-lodash'),
3637
require.resolve('@babel/plugin-syntax-dynamic-import'),

packages/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@
231231
"@babel/core": "^7.5.5",
232232
"@babel/helper-module-imports": "^7.0.0",
233233
"@babel/plugin-proposal-class-properties": "^7.5.5",
234-
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.7.4",
234+
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
235235
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
236236
"@babel/plugin-proposal-optional-chaining": "^7.7.4",
237237
"@babel/plugin-syntax-dynamic-import": "^7.2.0",

packages/app/src/app/components/CreateNewSandbox/queries.ts

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import gql from 'graphql-tag';
2-
import { client } from 'app/graphql/client';
3-
import immer from 'immer';
4-
import {
5-
addSandboxesToFolder,
6-
PATHED_SANDBOXES_CONTENT_QUERY,
7-
} from 'app/pages/Dashboard/queries';
8-
import { notificationState } from '@codesandbox/common/lib/utils/notifications';
91
import track from '@codesandbox/common/lib/utils/analytics';
2+
import { notificationState } from '@codesandbox/common/lib/utils/notifications';
103
import { NotificationStatus } from '@codesandbox/notifications';
4+
import { client } from 'app/graphql/client';
115
import {
12-
UnmakeSandboxesTemplateMutation,
13-
UnmakeSandboxesTemplateMutationVariables,
14-
ListTemplatesQueryVariables,
156
ListTemplatesQuery,
16-
PathedSandboxesQuery,
7+
ListTemplatesQueryVariables,
178
PathedSandboxesFoldersQueryVariables,
9+
PathedSandboxesQuery,
10+
UnmakeSandboxesTemplateMutation,
11+
UnmakeSandboxesTemplateMutationVariables,
1812
} from 'app/graphql/types';
13+
import {
14+
PATHED_SANDBOXES_CONTENT_QUERY,
15+
addSandboxesToFolder,
16+
} from 'app/pages/Dashboard/queries';
17+
import gql from 'graphql-tag';
18+
import immer from 'immer';
1919

2020
const TEMPLATE_FRAGMENT = gql`
2121
fragment Template on Template {
@@ -176,23 +176,32 @@ export function unmakeTemplates(selectedSandboxes: string[]) {
176176
});
177177

178178
const data = immer(oldTemplatesCache, draft => {
179-
draft.me.templates = draft.me.templates.filter(
180-
x => selectedSandboxes.indexOf(x.sandbox.id) === -1
181-
);
179+
if (draft?.me?.templates && draft?.me?.teams) {
180+
draft.me.templates = draft.me.templates.filter(x =>
181+
x?.sandbox?.id
182+
? selectedSandboxes.indexOf(x.sandbox.id) === -1
183+
: true
184+
);
182185

183-
draft.me.teams = draft.me.teams.map(t => ({
184-
...t,
185-
templates: t.templates.filter(
186-
x => selectedSandboxes.indexOf(x.sandbox.id) === -1
187-
),
188-
}));
186+
draft.me.teams = draft.me.teams.map(t => ({
187+
...t,
188+
templates: t?.templates?.filter(x =>
189+
x?.sandbox?.id
190+
? selectedSandboxes.indexOf(x.sandbox.id) === -1
191+
: true
192+
),
193+
// Giving up
194+
})) as any;
195+
}
189196
});
190197

191-
cache.writeQuery<ListTemplatesQuery, ListTemplatesQueryVariables>({
192-
query: LIST_OWNED_TEMPLATES,
193-
variables,
194-
data,
195-
});
198+
if (data) {
199+
cache.writeQuery<ListTemplatesQuery, ListTemplatesQueryVariables>({
200+
query: LIST_OWNED_TEMPLATES,
201+
variables,
202+
data,
203+
});
204+
}
196205
} catch (e) {
197206
// cache doesn't exist, no biggie!
198207
}
@@ -202,7 +211,7 @@ export function unmakeTemplates(selectedSandboxes: string[]) {
202211

203212
export function makeTemplates(
204213
selectedSandboxes: string[],
205-
teamId?: string,
214+
teamId: string | null,
206215
collections?: { teamId: string | null }[]
207216
) {
208217
const unpackedSelectedSandboxes: string[] =
@@ -238,9 +247,15 @@ export function makeTemplates(
238247
});
239248

240249
const data = immer(oldFolderCacheData, draft => {
241-
draft.me.collection.sandboxes = oldFolderCacheData.me.collection.sandboxes.filter(
242-
x => selectedSandboxes.indexOf(x.id) === -1
243-
);
250+
if (
251+
draft?.me?.collection &&
252+
oldFolderCacheData?.me?.collection?.sandboxes
253+
) {
254+
draft.me.collection.sandboxes = oldFolderCacheData.me.collection.sandboxes.filter(
255+
x =>
256+
x?.id ? selectedSandboxes.indexOf(x.id) === -1 : true
257+
);
258+
}
244259
});
245260

246261
cache.writeQuery({

packages/app/src/app/overmind/actions.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,20 @@ type ModalName =
7373
| 'searchDependencies'
7474
| 'share'
7575
| 'signInForTemplates'
76-
| 'userSurvey';
76+
| 'userSurvey'
77+
| 'liveSessionEnded';
7778

7879
export const modalOpened: Action<{
7980
modal: ModalName;
8081
message?: string;
8182
itemId?: string;
82-
}> = ({ state, effects }, { modal, message, itemId }) => {
83-
effects.analytics.track('Open Modal', { modal });
84-
state.currentModalMessage = message;
85-
state.currentModal = modal;
86-
if (state.currentModal === 'preferences') {
87-
state.preferences.itemId = itemId;
83+
}> = ({ state, effects }, props) => {
84+
effects.analytics.track('Open Modal', { modal: props.modal });
85+
state.currentModal = props.modal;
86+
if (props.modal === 'preferences' && props.itemId) {
87+
state.preferences.itemId = props.itemId;
88+
} else {
89+
state.currentModalMessage = props.message || null;
8890
}
8991
};
9092

@@ -162,8 +164,10 @@ export const signInZeitClicked: AsyncAction = async ({
162164
};
163165

164166
export const signOutZeitClicked: AsyncAction = async ({ state, effects }) => {
165-
await effects.api.signoutZeit();
166-
state.user.integrations.zeit = null;
167+
if (state.user?.integrations?.zeit) {
168+
await effects.api.signoutZeit();
169+
delete state.user.integrations.zeit;
170+
}
167171
};
168172

169173
export const authTokenRequested: AsyncAction = async ({ actions }) => {
@@ -200,8 +204,10 @@ export const signOutGithubIntegration: AsyncAction = async ({
200204
state,
201205
effects,
202206
}) => {
203-
await effects.api.signoutGithubIntegration();
204-
state.user.integrations.github = null;
207+
if (state.user?.integrations?.github) {
208+
await effects.api.signoutGithubIntegration();
209+
delete state.user.integrations.github;
210+
}
205211
};
206212

207213
export const setUpdateStatus: Action<{ status: string }> = (

packages/app/src/app/overmind/effects/browser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default {
4242
`scrollbars=no,toolbar=no,location=no,titlebar=no,directories=no,status=no,menubar=no, ${getPopupDimensions()}`
4343
);
4444
return {
45-
close: () => popup.close(),
45+
close: () => popup?.close(),
4646
};
4747
},
4848
waitForMessage<T>(type): Promise<T> {

packages/app/src/app/overmind/effects/git/export-to-github.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ import { Sandbox } from '@codesandbox/common/lib/types';
22
import JSZip from 'jszip';
33
import { createZip, BLOB_ID } from '../zip/create-zip';
44

5+
interface IAPIModule {
6+
content: string;
7+
isBinary: boolean;
8+
path: string;
9+
}
10+
511
export default async function deploy(sandbox: Sandbox) {
612
// We first get the zip file, this is what we essentially need to have deployed.
713
// So we convert it to an API request that ZEIT will understand
@@ -19,14 +25,14 @@ export default async function deploy(sandbox: Sandbox) {
1925

2026
const contents = await JSZip.loadAsync(zipFile);
2127

22-
const apiData = { sandbox: [] };
28+
const apiData: { sandbox: IAPIModule[] } = { sandbox: [] };
2329
const filePaths = Object.keys(contents.files);
2430
for (let i = 0; i < filePaths.length; i += 1) {
2531
const filePath = filePaths[i];
2632
const file = contents.files[filePath];
2733

2834
if (!file.dir) {
29-
let content = await file.async('text'); // eslint-disable-line no-await-in-loop
35+
let content: string = await file.async('text'); // eslint-disable-line no-await-in-loop
3036
let isBinary = false;
3137

3238
// It's marked as a binary

packages/app/src/app/overmind/effects/keybindingManager.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ const isIOS =
1212
Boolean(navigator.platform.match(/(iPhone|iPod|iPad)/i));
1313

1414
const state = {
15-
keybindings: null,
15+
keybindings: null as Array<{ key: string; bindings: string[] }> | null,
1616
keydownIndex: 0,
17-
pendingPrimaryBindings: [],
18-
pendingSecondaryBindings: [],
19-
timeout: null,
17+
pendingPrimaryBindings: [] as Array<{ key: string; bindings: string[] }>,
18+
pendingSecondaryBindings: [] as Array<{ key: string; bindings: string[] }>,
19+
timeout: null as NodeJS.Timeout | null,
2020
};
2121

2222
function reset() {
@@ -222,7 +222,7 @@ function handleKeyDown(overmindInstance, e) {
222222
// We filter out any hits on full list of bindings on first key down, or just move
223223
// on filtering on existing pending bindings
224224
state.pendingPrimaryBindings = (state.keydownIndex === 0
225-
? state.keybindings
225+
? state.keybindings || []
226226
: state.pendingPrimaryBindings
227227
).filter(
228228
binding =>
@@ -277,8 +277,8 @@ function handleKeyDown(overmindInstance, e) {
277277
}
278278
}
279279

280-
let onKeyUp = null;
281-
let onKeyDown = null;
280+
let onKeyUp: EventListenerOrEventListenerObject | null = null;
281+
let onKeyDown: EventListenerOrEventListenerObject | null = null;
282282
let isStarted = false;
283283
let _overmindInstance;
284284

@@ -289,7 +289,10 @@ export default {
289289
onKeyUp = handleKeyUp.bind(null);
290290
},
291291
set(userKeybindings = []) {
292-
const keybindings = [...userKeybindings];
292+
const keybindings = [...userKeybindings] as Array<{
293+
key: string;
294+
bindings: string[];
295+
}>;
293296

294297
Object.keys(KEYBINDINGS).forEach(bindingName => {
295298
if (keybindings.find(x => x.key === bindingName)) {
@@ -314,13 +317,17 @@ export default {
314317
return;
315318
}
316319

317-
window.addEventListener('keydown', onKeyDown);
318-
window.addEventListener('keyup', onKeyUp);
319-
isStarted = true;
320+
if (onKeyDown && onKeyUp) {
321+
window.addEventListener('keydown', onKeyDown);
322+
window.addEventListener('keyup', onKeyUp);
323+
isStarted = true;
324+
}
320325
},
321326
pause() {
322-
window.removeEventListener('keydown', onKeyDown);
323-
window.removeEventListener('keyup', onKeyUp);
324-
isStarted = false;
327+
if (onKeyDown && onKeyUp) {
328+
window.removeEventListener('keydown', onKeyDown);
329+
window.removeEventListener('keyup', onKeyUp);
330+
isStarted = false;
331+
}
325332
},
326333
};

packages/app/src/app/overmind/effects/live/clients.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export default (
9090
client = this.create(moduleShortid, revision);
9191
}
9292

93-
return client;
93+
return client!;
9494
},
9595
create(moduleShortid, initialRevision) {
9696
const client = new CodeSandboxOTClient(

0 commit comments

Comments
 (0)