Skip to content

Commit 9a7c981

Browse files
committed
Base upload fix
1 parent 5e4931e commit 9a7c981

File tree

7 files changed

+111
-34
lines changed

7 files changed

+111
-34
lines changed

site/js-untar.d.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
declare module "js-untar" {
2-
interface File {
2+
export interface File {
33
name: string
4+
mode: string
45
blob: Blob
6+
gid: number
7+
uid: number
8+
mtime: number
9+
type: "0" | "1" | "2" | "3" | "4" | "5" //https://en.wikipedia.org/wiki/Tar_(computing) on Type flag field
510
}
611

712
const Untar: (buffer: ArrayBuffer) => {
813
then: (
9-
resolve?: () => Promise<void>,
14+
resolve?: (files: File[]) => void,
1015
reject?: () => Promise<void>,
11-
progress: (file: File) => Promise<void>,
16+
progress?: (file: File) => Promise<void>,
1217
) => Promise<void>
1318
}
1419

site/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"@tanstack/react-query": "4.22.4",
4040
"@testing-library/react-hooks": "8.0.1",
4141
"@types/color-convert": "2.0.0",
42+
"@types/file-saver": "^2.0.5",
4243
"@types/react-color": "3.0.6",
4344
"@vitejs/plugin-react": "2.1.0",
4445
"@xstate/inspect": "0.6.5",
@@ -54,6 +55,7 @@
5455
"dayjs": "1.11.4",
5556
"emoji-mart": "5.4.0",
5657
"eventsourcemock": "2.0.0",
58+
"file-saver": "^2.0.5",
5759
"formik": "2.2.9",
5860
"front-matter": "4.0.2",
5961
"history": "5.3.0",

site/src/pages/TemplateVersionPage/TemplateVersionEditorPage/TemplateVersionEditorPage.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,21 @@ type Params = {
1616
export const TemplateVersionEditorPage: FC = () => {
1717
const { version: versionName, template: templateName } = useParams() as Params
1818
const orgId = useOrganizationId()
19-
const { isSuccess, data } = useTemplateVersionData(
20-
orgId,
21-
templateName,
22-
versionName,
23-
)
2419
const [editorState, sendEvent] = useMachine(templateVersionEditorMachine, {
2520
context: { orgId },
2621
})
22+
const { isSuccess, data } = useTemplateVersionData(
23+
{
24+
orgId,
25+
templateName,
26+
versionName,
27+
},
28+
{
29+
onSuccess(data) {
30+
sendEvent({ type: "INITIALIZE", untarFiles: data.untarFiles })
31+
},
32+
},
33+
)
2734

2835
return (
2936
<>
@@ -34,7 +41,7 @@ export const TemplateVersionEditorPage: FC = () => {
3441
{isSuccess && (
3542
<TemplateVersionEditor
3643
template={data.template}
37-
templateVersion={editorState.context.version || data.currentVersion}
44+
templateVersion={editorState.context.version || data.version}
3845
defaultFileTree={data.fileTree}
3946
onPreview={(fileTree) => {
4047
sendEvent({
Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,49 @@
1-
import { useQuery } from "@tanstack/react-query"
2-
import { getTemplateByName, getTemplateVersionByName } from "api/api"
1+
import { useQuery, UseQueryOptions } from "@tanstack/react-query"
2+
import { getFile, getTemplateByName, getTemplateVersionByName } from "api/api"
33
import { createTemplateVersionFileTree } from "util/templateVersion"
4+
import untar, { File as UntarFile } from "js-untar"
45

56
const getTemplateVersionData = async (
67
orgId: string,
78
templateName: string,
89
versionName: string,
910
) => {
10-
const [template, currentVersion] = await Promise.all([
11+
const [template, version] = await Promise.all([
1112
getTemplateByName(orgId, templateName),
1213
getTemplateVersionByName(orgId, templateName, versionName),
1314
])
14-
const fileTree = await createTemplateVersionFileTree(currentVersion)
15+
const tarFile = await getFile(version.job.file_id)
16+
let untarFiles: UntarFile[] = []
17+
await untar(tarFile).then((files) => {
18+
untarFiles = files
19+
})
20+
const fileTree = await createTemplateVersionFileTree(untarFiles)
1521

1622
return {
1723
template,
18-
currentVersion,
24+
version,
1925
fileTree,
26+
untarFiles,
2027
}
2128
}
2229

30+
type GetTemplateVersionResponse = Awaited<
31+
ReturnType<typeof getTemplateVersionData>
32+
>
33+
34+
type UseTemplateVersionDataParams = {
35+
orgId: string
36+
templateName: string
37+
versionName: string
38+
}
39+
2340
export const useTemplateVersionData = (
24-
orgId: string,
25-
templateName: string,
26-
versionName: string,
41+
{ templateName, versionName, orgId }: UseTemplateVersionDataParams,
42+
options?: UseQueryOptions<GetTemplateVersionResponse>,
2743
) => {
2844
return useQuery({
2945
queryKey: ["templateVersion", templateName, versionName],
3046
queryFn: () => getTemplateVersionData(orgId, templateName, versionName),
47+
...options,
3148
})
3249
}

site/src/util/templateVersion.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as API from "api/api"
22
import { TemplateVersion } from "api/typesGenerated"
3-
import untar from "js-untar"
3+
import untar, { File as UntarFile } from "js-untar"
44
import { FileTree, setFile } from "./filetree"
55

66
/**
@@ -41,21 +41,22 @@ export const getTemplateVersionFiles = async (
4141

4242
const allowedExtensions = ["tf", "md", "Dockerfile"]
4343

44+
export const isAllowedFile = (name: string) => {
45+
return allowedExtensions.some((ext) => name.endsWith(ext))
46+
}
47+
4448
export const createTemplateVersionFileTree = async (
45-
version: TemplateVersion,
49+
untarFiles: UntarFile[],
4650
): Promise<FileTree> => {
4751
let fileTree: FileTree = {}
48-
const tarFile = await API.getFile(version.job.file_id)
4952
const blobs: Record<string, Blob> = {}
5053

51-
await untar(tarFile).then(undefined, undefined, async (file) => {
52-
if (allowedExtensions.some((ext) => file.name.endsWith(ext))) {
53-
blobs[file.name] = file.blob
54+
for (const untarFile of untarFiles) {
55+
if (isAllowedFile(untarFile.name)) {
56+
blobs[untarFile.name] = untarFile.blob
5457
}
55-
})
58+
}
5659

57-
// We don't want to get the blob text during untar to not block the main thread.
58-
// Also, by doing it here, we can make all the loading in parallel.
5960
await Promise.all(
6061
Object.entries(blobs).map(async ([fullPath, blob]) => {
6162
const content = await blob.text()

site/src/xServices/templateVersionEditor/templateVersionEditorXService.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import {
88
import { assign, createMachine } from "xstate"
99
import * as API from "api/api"
1010
import Tar from "tar-js"
11+
import { File as UntarFile } from "js-untar"
1112
import { FileTree, traverse } from "util/filetree"
13+
import { isAllowedFile } from "util/templateVersion"
14+
import { saveAs } from "file-saver"
1215

1316
export interface CreateVersionData {
1417
file: File
@@ -22,6 +25,7 @@ export interface TemplateVersionEditorMachineContext {
2225
version?: TemplateVersion
2326
resources?: WorkspaceResource[]
2427
buildLogs?: ProvisionerJobLog[]
28+
untarFiles?: UntarFile[]
2529
}
2630

2731
export const templateVersionEditorMachine = createMachine(
@@ -31,6 +35,7 @@ export const templateVersionEditorMachine = createMachine(
3135
schema: {
3236
context: {} as TemplateVersionEditorMachineContext,
3337
events: {} as
38+
| { type: "INITIALIZE"; untarFiles: UntarFile[] }
3439
| {
3540
type: "CREATE_VERSION"
3641
fileTree: FileTree
@@ -61,8 +66,16 @@ export const templateVersionEditorMachine = createMachine(
6166
},
6267
},
6368
tsTypes: {} as import("./templateVersionEditorXService.typegen").Typegen0,
64-
initial: "idle",
69+
initial: "initializing",
6570
states: {
71+
initializing: {
72+
on: {
73+
INITIALIZE: {
74+
actions: ["assignUntarFiles"],
75+
target: "idle",
76+
},
77+
},
78+
},
6679
idle: {
6780
on: {
6881
CREATE_VERSION: {
@@ -201,20 +214,42 @@ export const templateVersionEditorMachine = createMachine(
201214
}
202215
},
203216
}),
217+
assignUntarFiles: assign({
218+
untarFiles: (_, { untarFiles }) => untarFiles,
219+
}),
204220
},
205221
services: {
206-
uploadTar: (ctx) => {
207-
if (!ctx.fileTree) {
208-
throw new Error("files must be set")
222+
uploadTar: async ({ fileTree, untarFiles }) => {
223+
if (!fileTree) {
224+
throw new Error("file tree must to be set")
225+
}
226+
if (!untarFiles) {
227+
throw new Error("untar files must to be set")
209228
}
210229
const tar = new Tar()
211-
let out: Uint8Array = new Uint8Array()
212-
traverse(ctx.fileTree, (content, _filename, fullPath) => {
230+
// Add previous non editable files
231+
for (const untarFile of untarFiles) {
232+
if (!isAllowedFile(untarFile.name) && untarFile.type === "0") {
233+
// TODO: Maybe there is a way to use blob directly to append in tar
234+
// or a way where converting to text is necessary. I tried to find
235+
// it but I didn't have success tho.
236+
const content = await untarFile.blob.text()
237+
tar.append(untarFile.name, content, {
238+
mode: Number(untarFile.mode),
239+
gid: untarFile.gid,
240+
uid: untarFile.uid,
241+
mtime: untarFile.mtime,
242+
})
243+
}
244+
}
245+
// Add the editable files
246+
traverse(fileTree, (content, _filename, fullPath) => {
213247
if (typeof content === "string") {
214-
out = tar.append(fullPath, content)
248+
tar.append(fullPath, content)
215249
}
216250
})
217-
return API.uploadTemplateFile(new File([out], "template.tar"))
251+
saveAs(new Blob([tar.out]), "template.tar")
252+
return API.uploadTemplateFile(new File([tar.out], "template.tar"))
218253
},
219254
createBuild: (ctx) => {
220255
if (!ctx.uploadResponse) {

site/yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3144,6 +3144,11 @@
31443144
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40"
31453145
integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==
31463146

3147+
"@types/file-saver@^2.0.5":
3148+
version "2.0.5"
3149+
resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.5.tgz#9ee342a5d1314bb0928375424a2f162f97c310c7"
3150+
integrity sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==
3151+
31473152
"@types/glob@*":
31483153
version "8.0.0"
31493154
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.0.0.tgz#321607e9cbaec54f687a0792b2d1d370739455d2"
@@ -7278,6 +7283,11 @@ file-loader@^6.2.0:
72787283
loader-utils "^2.0.0"
72797284
schema-utils "^3.0.0"
72807285

7286+
file-saver@^2.0.5:
7287+
version "2.0.5"
7288+
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
7289+
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
7290+
72817291
file-system-cache@^1.0.5:
72827292
version "1.1.0"
72837293
resolved "https://registry.yarnpkg.com/file-system-cache/-/file-system-cache-1.1.0.tgz#984de17b976b75a77a27e08d6828137c1aa80fa1"

0 commit comments

Comments
 (0)