Skip to content

Commit 7e4a81c

Browse files
authored
Support binary files when creating github repo (codesandbox#1483)
1 parent e9cdd3f commit 7e4a81c

File tree

3 files changed

+65
-27
lines changed

3 files changed

+65
-27
lines changed

packages/app/src/app/store/providers/Git/export-to-github.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import JSZip from 'jszip';
2-
import { createZip } from '../Utils/create-zip';
2+
import { createZip, BLOB_ID } from '../Utils/create-zip';
33

44
export default async function deploy(sandbox) {
55
// We first get the zip file, this is what we essentially need to have deployed.
66
// So we convert it to an API request that ZEIT will understand
77
const zipFile = await createZip(
88
sandbox,
99
sandbox.modules,
10-
sandbox.directories
10+
sandbox.directories,
11+
false
1112
);
1213

1314
if (!zipFile) {
@@ -23,9 +24,18 @@ export default async function deploy(sandbox) {
2324
const file = contents.files[filePath];
2425

2526
if (!file.dir) {
27+
let content = await file.async('text'); // eslint-disable-line no-await-in-loop
28+
let isBinary = false;
29+
30+
// It's marked as a binary
31+
if (content.startsWith(BLOB_ID)) {
32+
isBinary = true;
33+
content = content.replace(BLOB_ID, '');
34+
}
35+
2636
apiData.sandbox.push({
27-
content: await file.async('text'), // eslint-disable-line no-await-in-loop
28-
isBinary: false,
37+
content,
38+
isBinary,
2939
path: filePath,
3040
});
3141
}

packages/app/src/app/store/providers/Utils/create-zip/full/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ export default async function createZip(
55
zip,
66
sandbox: Sandbox,
77
modules: Array<Module>,
8-
directories: Array<Directory>
8+
directories: Array<Directory>,
9+
downloadBlobs: boolean
910
) {
1011
await Promise.all(
1112
modules
1213
.filter(x => x.directoryShortid == null)
1314
.filter(x => x.title !== 'yarn.lock' && x.title !== 'package-lock.json')
14-
.map(x => createFile(x, zip))
15+
.map(x => createFile(x, zip, downloadBlobs))
1516
);
1617

1718
await Promise.all(
1819
directories
1920
.filter(x => x.directoryShortid == null)
20-
.map(x => createDirectoryWithFiles(modules, directories, x, zip))
21+
.map(x =>
22+
createDirectoryWithFiles(modules, directories, x, zip, downloadBlobs)
23+
)
2124
);
2225

2326
return zip;

packages/app/src/app/store/providers/Utils/create-zip/index.js

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { Sandbox, Module, Directory } from 'common/types';
66
import { react, reactTs, vue, preact, svelte } from 'common/templates/index';
77
import { resolveModule } from 'common/sandbox/modules';
88

9+
export const BLOB_ID = 'blob-url://';
10+
911
const CSSTag = (resource: string) =>
1012
`<link rel="stylesheet" type="text/css" href="${resource}" media="all">`;
1113
const JSTag = (resource: string) =>
@@ -130,19 +132,31 @@ export function createPackageJSON(
130132
);
131133
}
132134

133-
export async function createFile(module: Module, zip) {
135+
export async function createFile(
136+
module: Module,
137+
zip: JSZip,
138+
downloadBlobs: boolean = true
139+
) {
134140
if (module.isBinary) {
135-
const code = await window.fetch(module.code).then(x => {
136-
const contentType = x.headers['Content-Type'];
141+
if (downloadBlobs) {
142+
const code = await window.fetch(module.code).then(x => {
143+
const contentType = x.headers['Content-Type'];
144+
145+
if (contentType && contentType.startsWith('text/plain')) {
146+
return x.text();
147+
}
148+
149+
return x.blob();
150+
});
137151

138-
if (contentType && contentType.startsWith('text/plain')) {
139-
return x.text();
140-
}
152+
return zip.file(module.title, code);
153+
}
141154

142-
return x.blob();
143-
});
155+
// Mark that the module is a link to a blob
156+
const code = `${BLOB_ID}${module.code}`;
157+
const file = zip.file(module.title, code);
144158

145-
return zip.file(module.title, code);
159+
return file;
146160
}
147161

148162
return zip.file(module.title, module.code);
@@ -152,27 +166,31 @@ export async function createDirectoryWithFiles(
152166
modules: Array<Module>,
153167
directories: Array<Directory>,
154168
directory: Directory,
155-
zip
169+
zip: JSZip,
170+
downloadBlobs: boolean = true
156171
) {
157172
const newZip = zip.folder(directory.title);
158173

159174
await Promise.all(
160175
modules
161176
.filter(x => x.directoryShortid === directory.shortid)
162-
.map(x => createFile(x, newZip))
177+
.map(x => createFile(x, newZip, downloadBlobs))
163178
);
164179

165180
await Promise.all(
166181
directories
167182
.filter(x => x.directoryShortid === directory.shortid)
168-
.map(x => createDirectoryWithFiles(modules, directories, x, newZip))
183+
.map(x =>
184+
createDirectoryWithFiles(modules, directories, x, newZip, downloadBlobs)
185+
)
169186
);
170187
}
171188

172189
export async function createZip(
173190
sandbox: Sandbox,
174191
modules: Array<Module>,
175-
directories: Array<Directory>
192+
directories: Array<Directory>,
193+
downloadBlobs: boolean = true
176194
) {
177195
const zip = new JSZip();
178196

@@ -186,32 +204,39 @@ export async function createZip(
186204
// This is a full project, with all files already in there. We need to create
187205
// a zip by just adding all existing files to it (downloading binaries too).
188206
promise = import(/* webpackChunkName: 'full-zip' */ './full').then(
189-
generator => generator.default(zip, sandbox, modules, directories)
207+
generator =>
208+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
190209
);
191210
} else if (sandbox.template === react.name) {
192211
promise = import(/* webpackChunkName: 'create-react-app-zip' */ './create-react-app').then(
193-
generator => generator.default(zip, sandbox, modules, directories)
212+
generator =>
213+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
194214
);
195215
} else if (sandbox.template === reactTs.name) {
196216
promise = import(/* webpackChunkName: 'create-react-app-typescript-zip' */ './create-react-app-typescript').then(
197-
generator => generator.default(zip, sandbox, modules, directories)
217+
generator =>
218+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
198219
);
199220
} else if (sandbox.template === vue.name) {
200221
promise = import(/* webpackChunkName: 'vue-zip' */ './vue-cli').then(
201-
generator => generator.default(zip, sandbox, modules, directories)
222+
generator =>
223+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
202224
);
203225
} else if (sandbox.template === preact.name) {
204226
promise = import(/* webpackChunkName: 'preact-zip' */ './preact-cli').then(
205-
generator => generator.default(zip, sandbox, modules, directories)
227+
generator =>
228+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
206229
);
207230
} else if (sandbox.template === svelte.name) {
208231
promise = import(/* webpackChunkName: 'svelte-zip' */ './svelte').then(
209-
generator => generator.default(zip, sandbox, modules, directories)
232+
generator =>
233+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
210234
);
211235
} else {
212236
// If no specific zip generator is found we will default to the full generator
213237
promise = import(/* webpackChunkName: 'full-zip' */ './full').then(
214-
generator => generator.default(zip, sandbox, modules, directories)
238+
generator =>
239+
generator.default(zip, sandbox, modules, directories, downloadBlobs)
215240
);
216241
}
217242

0 commit comments

Comments
 (0)