Skip to content

Commit b381d49

Browse files
Refactored to imperative file system approach
1 parent 70a0389 commit b381d49

File tree

15 files changed

+382
-346
lines changed

15 files changed

+382
-346
lines changed

packages/app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@
150150
"normalizr": "^3.2.3",
151151
"onigasm": "^2.2.1",
152152
"ot": "^0.0.15",
153-
"overmind": "^20.1.0-1571936446466",
153+
"overmind": "^20.1.0-1572182984474",
154154
"overmind-devtools": "^19.0.0",
155-
"overmind-react": "^21.1.0-1571936446466",
155+
"overmind-react": "^21.1.0-1572182984474",
156156
"phoenix": "^1.3.0",
157157
"postcss": "^6.0.9",
158158
"postcss-selector-parser": "^2.2.3",

packages/app/src/app/overmind/effects/api/apiFactory.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
33
import { logError } from '@codesandbox/common/lib/utils/analytics';
44
import { values } from 'lodash-es';
55
import { camelizeKeys, decamelizeKeys } from 'humps';
6-
import { Module } from '@codesandbox/common/lib/types';
76

87
export const API_ROOT = '/api/v1';
98

@@ -28,9 +27,6 @@ export type Api = {
2827

2928
export type ApiConfig = {
3029
provideJwtToken: () => string;
31-
getModulesByPath: () => {
32-
[path: string]: Module;
33-
};
3430
getParsedConfigurations: () => any;
3531
onError: (error: string) => void;
3632
};

packages/app/src/app/overmind/effects/vscode/ModelsHandler.ts

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,33 +88,40 @@ export class ModelsHandler {
8888
return Promise.resolve();
8989
};
9090

91-
public updateModules = () => {
92-
Object.keys(this.modelListeners).forEach(path => {
93-
const shortid = this.modelListeners[path].moduleShortid;
94-
const { model } = this.modelListeners[path];
95-
const module = this.sandbox.modules.find(m => m.shortid === shortid);
96-
if (!module) {
97-
// Deleted
98-
return;
99-
}
91+
public updateModules = () =>
92+
Promise.all(
93+
Object.keys(this.modelListeners).map(path => {
94+
const shortid = this.modelListeners[path].moduleShortid;
95+
const { model } = this.modelListeners[path];
96+
const module = this.sandbox.modules.find(m => m.shortid === shortid);
97+
if (!module) {
98+
// Deleted
99+
return Promise.resolve();
100+
}
100101

101-
const modulePath = getVSCodePath(this.sandbox, module.id);
102-
103-
if (modulePath !== model.uri.path) {
104-
this.editorApi.textFileService
105-
.move(model.uri, this.monaco.Uri.file(modulePath))
106-
.then(() => {
107-
const editor = this.editorApi.getActiveCodeEditor();
108-
const currentModel = editor && editor.getModel();
109-
const isCurrentFile =
110-
currentModel && currentModel.uri.path === path;
111-
if (isCurrentFile) {
112-
this.editorApi.openFile(modulePath.replace('/sandbox', ''));
113-
}
114-
});
115-
}
116-
});
117-
};
102+
const modulePath = getVSCodePath(this.sandbox, module.id);
103+
104+
if (modulePath !== model.uri.path) {
105+
return this.editorApi.textFileService
106+
.move(model.uri, this.monaco.Uri.file(modulePath))
107+
.then(() => {
108+
const editor = this.editorApi.getActiveCodeEditor();
109+
const currentModel = editor && editor.getModel();
110+
const isCurrentFile =
111+
currentModel && currentModel.uri.path === path;
112+
if (isCurrentFile) {
113+
return this.editorApi.openFile(
114+
modulePath.replace('/sandbox', '')
115+
);
116+
}
117+
118+
return Promise.resolve();
119+
});
120+
}
121+
122+
return Promise.resolve();
123+
})
124+
);
118125

119126
public applyOperations(operations: { [moduleShortid: string]: any }) {
120127
const operationsJSON = operations.toJSON ? operations.toJSON() : operations;

packages/app/src/app/overmind/effects/vscode/extensionHostWorker/common/fs.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { FileSystemConfiguration } from '../../../../../../../standalone-packages/codesandbox-browserfs';
1+
import { writeFile, rename, rmdir, unlink, mkdir } from '../../fs/utils';
2+
import { FileSystemConfiguration } from '../../../../../../../../../standalone-packages/codesandbox-browserfs';
23
import { getTypeFetcher } from './type-downloader';
34
import { EXTENSIONS_LOCATION } from '../../constants';
45

@@ -49,7 +50,7 @@ export async function initializeBrowserFS({
4950
} = {}) {
5051
return new Promise(async resolve => {
5152
const config = { ...BROWSER_FS_CONFIG };
52-
let modulesByPath = {};
53+
let currentSandboxFs = {};
5354

5455
if (syncSandbox) {
5556
if (syncTypes) {
@@ -65,9 +66,7 @@ export async function initializeBrowserFS({
6566
fs: 'CodeSandboxEditorFS',
6667
options: {
6768
api: {
68-
getState: () => ({
69-
modulesByPath,
70-
}),
69+
getSandboxFs: () => currentSandboxFs,
7170
},
7271
},
7372
};
@@ -84,12 +83,42 @@ export async function initializeBrowserFS({
8483

8584
if (syncSandbox) {
8685
self.addEventListener('message', evt => {
87-
if (evt.data.$type === 'file-sync') {
88-
modulesByPath = evt.data.$data;
86+
switch (evt.data.$type) {
87+
case 'sandbox-fs': {
88+
currentSandboxFs = evt.data.$data;
8989

90-
if (!resolved) {
91-
resolve();
92-
resolved = true;
90+
console.log('HEEEEEY', currentSandboxFs);
91+
92+
if (!resolved) {
93+
resolve();
94+
resolved = true;
95+
}
96+
break;
97+
}
98+
case 'writeFile': {
99+
const { path, module } = evt.data.$data;
100+
writeFile(currentSandboxFs, path, module);
101+
break;
102+
}
103+
case 'rename': {
104+
const { fromPath, toPath } = evt.data.$data;
105+
rename(currentSandboxFs, fromPath, toPath);
106+
break;
107+
}
108+
case 'rmdir': {
109+
const { removePath } = evt.data.$data;
110+
rmdir(currentSandboxFs, removePath);
111+
break;
112+
}
113+
case 'unlink': {
114+
const { removePath } = evt.data.$data;
115+
unlink(currentSandboxFs, removePath);
116+
break;
117+
}
118+
case 'mkdir': {
119+
const { path, directory } = evt.data.$data;
120+
mkdir(currentSandboxFs, path, directory);
121+
break;
93122
}
94123
}
95124
});

packages/app/src/app/overmind/effects/vscode/browserFs/index.ts renamed to packages/app/src/app/overmind/effects/vscode/fs/index.ts

Lines changed: 126 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
import { dirname } from 'path';
2+
13
import { getAbsoluteDependencies } from '@codesandbox/common/lib/utils/dependencies';
24
import { getGlobal } from '@codesandbox/common/lib/utils/global';
35
import { protocolAndHost } from '@codesandbox/common/lib/utils/url-generator';
46
import { json } from 'overmind';
5-
7+
import {
8+
getDirectoryPath,
9+
getModulePath,
10+
} from '@codesandbox/common/lib/sandbox/modules';
11+
import { SandboxFs, Module, Directory } from '@codesandbox/common/lib/types';
612
import { EXTENSIONS_LOCATION } from '../constants';
713
import { getTypeFetcher } from '../extensionHostWorker/common/type-downloader';
14+
import { writeFile, rename, rmdir, unlink, mkdir } from './utils';
815

916
const global = getGlobal() as Window & { BrowserFS: any };
1017

11-
const fs = global.BrowserFS.BFSRequire('fs');
18+
const browserFs = global.BrowserFS.BFSRequire('fs');
1219
const SERVICE_URL = 'https://ata-fetcher.cloud/api/v5/typings';
1320

1421
let lastMTime = new Date(0);
@@ -108,40 +115,43 @@ async function syncDependencyTypings(
108115
}
109116
}
110117

111-
function sendFiles(modulesByPath) {
118+
function sendSandboxFs(sandboxFs) {
112119
global.postMessage(
113120
{
114121
$broadcast: true,
115-
$type: 'file-sync',
116-
$data: json(modulesByPath),
122+
$type: 'sandbox-fs',
123+
$data: json(sandboxFs),
117124
},
118125
protocolAndHost()
119126
);
120127

121128
try {
122-
fs.stat('/sandbox/package.json', (packageJsonError, stat) => {
129+
browserFs.stat('/sandbox/package.json', (packageJsonError, stat) => {
123130
if (packageJsonError) {
124131
return;
125132
}
126133

127134
if (stat.mtime.toString() !== lastMTime.toString()) {
128135
lastMTime = stat.mtime;
129136

130-
fs.readFile(
137+
browserFs.readFile(
131138
'/sandbox/package.json',
132139
async (packageJsonReadError, rv) => {
133140
if (packageJsonReadError) {
134141
console.error(packageJsonReadError);
135142
return;
136143
}
137144

138-
fs.stat('/sandbox/tsconfig.json', (tsConfigError, result) => {
139-
// If tsconfig exists we want to sync the types
140-
syncDependencyTypings(
141-
rv.toString(),
142-
Boolean(tsConfigError) || !result
143-
);
144-
});
145+
browserFs.stat(
146+
'/sandbox/tsconfig.json',
147+
(tsConfigError, result) => {
148+
// If tsconfig exists we want to sync the types
149+
syncDependencyTypings(
150+
rv.toString(),
151+
Boolean(tsConfigError) || !result
152+
);
153+
}
154+
);
145155
}
146156
);
147157
}
@@ -152,19 +162,15 @@ function sendFiles(modulesByPath) {
152162
}
153163

154164
export default {
155-
initialize(options: {
156-
onModulesByPathChange: (modulesByPath: any) => void;
157-
getModulesByPath: () => any;
158-
getState: any;
159-
}) {
165+
initialize(options: { getSandboxFs: () => SandboxFs }) {
160166
self.addEventListener('message', evt => {
161167
if (evt.data.$type === 'request-data') {
162168
sendTypes();
163-
sendFiles(options.getModulesByPath());
169+
sendSandboxFs(options.getSandboxFs());
164170
}
165171
});
166172

167-
options.onModulesByPathChange(sendFiles);
173+
sendSandboxFs(options.getSandboxFs());
168174

169175
return new Promise((resolve, reject) => {
170176
window.BrowserFS.configure(
@@ -176,11 +182,7 @@ export default {
176182
fs: 'CodeSandboxEditorFS',
177183
options: {
178184
api: {
179-
getState: () => ({
180-
modulesByPath: options.getState().editor.currentSandbox
181-
? options.getState().editor.modulesByPath
182-
: {},
183-
}),
185+
getSandboxFs: options.getSandboxFs,
184186
},
185187
},
186188
},
@@ -218,4 +220,102 @@ export default {
218220
);
219221
});
220222
},
223+
224+
create(modules: Module[], directories: Directory[]): SandboxFs {
225+
const paths = {};
226+
227+
modules.forEach(m => {
228+
const path = getModulePath(modules, directories, m.id);
229+
if (path) {
230+
paths[path] = {
231+
...m,
232+
type: 'file',
233+
};
234+
}
235+
});
236+
237+
directories.forEach(d => {
238+
const path = getDirectoryPath(modules, directories, d.id);
239+
240+
// If this is a single directory with no children
241+
if (!Object.keys(paths).some(p => dirname(p) === path)) {
242+
paths[path] = { ...d, type: 'directory' };
243+
}
244+
});
245+
246+
return paths;
247+
},
248+
249+
writeFile(fs: SandboxFs, path: string, module: Module) {
250+
writeFile(fs, path, module);
251+
global.postMessage(
252+
{
253+
$broadcast: true,
254+
$type: 'write-file',
255+
$data: {
256+
path,
257+
module: json(module),
258+
},
259+
},
260+
protocolAndHost()
261+
);
262+
},
263+
264+
rename(fs: SandboxFs, fromPath: string, toPath: string) {
265+
rename(fs, fromPath, toPath);
266+
global.postMessage(
267+
{
268+
$broadcast: true,
269+
$type: 'rename',
270+
$data: {
271+
fromPath,
272+
toPath,
273+
},
274+
},
275+
protocolAndHost()
276+
);
277+
},
278+
279+
rmdir(fs: SandboxFs, removePath: string) {
280+
rmdir(fs, removePath);
281+
global.postMessage(
282+
{
283+
$broadcast: true,
284+
$type: 'rmdir',
285+
$data: {
286+
removePath,
287+
},
288+
},
289+
protocolAndHost()
290+
);
291+
},
292+
293+
unlink(fs: SandboxFs, removePath: string) {
294+
unlink(fs, removePath);
295+
global.postMessage(
296+
{
297+
$broadcast: true,
298+
$type: 'unlink',
299+
$data: {
300+
removePath,
301+
},
302+
},
303+
protocolAndHost()
304+
);
305+
},
306+
307+
mkdir(fs: SandboxFs, path: string, directory: Directory) {
308+
mkdir(fs, path, directory);
309+
global.postMessage(
310+
{
311+
$broadcast: true,
312+
$type: 'mkdir',
313+
$data: {
314+
path,
315+
directory: json(directory),
316+
},
317+
},
318+
protocolAndHost()
319+
);
320+
},
221321
};

0 commit comments

Comments
 (0)