wcz-layout
Version:
1 lines • 14.4 kB
Source Map (JSON)
{"version":3,"file":"file-DM1x40eJ.mjs","names":["createServerFn","setResponseHeaders","https","Readable","DefaultHttpStack","Upload","uuidv7","z","serverEnv","getAppToken","getAccessToken","apiMiddleware","authenticationMiddleware","FileMeta","FileMetaSchema","GetFileMetasSchema","object","appName","string","min","max","subId","uuid","FileSchema","id","UpdateFileMetaSchema","extend","fileName","DeleteFileSchema","BatchDeleteFilesSchema","UploadFileResult","UploadFileMetaSchema","file","instanceof","File","getFileMetas","method","validator","middleware","baseURL","scopeKey","handler","data","context","queryParams","URLSearchParams","append","fileMetas","api","request","Array","url","toString","getFileThumbnail","response","responseType","Headers","headers","toWeb","ReadableStream","getFile","downloadFile","updateFileMeta","deleteFile","batchDeleteFiles","insecureHttpsAgent","Agent","rejectUnauthorized","uploadFile","FormData","parse","get","Promise","accessToken","stream","fromWeb","dotIndex","name","lastIndexOf","fileExtension","slice","resolve","reject","upload","endpoint","FILE_BASE_URL","httpStack","agent","uploadSize","size","chunkSize","metadata","mimeType","type","Authorization","onError","onSuccess","start"],"sources":["../src/data/server/file.ts"],"sourcesContent":["import { createServerFn } from \"@tanstack/react-start\";\nimport { setResponseHeaders } from \"@tanstack/react-start/server\";\nimport https from \"node:https\";\nimport { Readable } from \"node:stream\";\nimport { DefaultHttpStack, Upload } from \"tus-js-client\";\nimport { uuidv7 } from \"uuidv7\";\nimport { z } from \"zod\";\nimport { serverEnv } from \"~/env\";\nimport { getAppToken } from \"~/lib/auth/msalServer\";\nimport { getAccessToken } from \"~/lib/auth/user\";\nimport { apiMiddleware } from \"~/middleware/apiMiddleware\";\nimport { authenticationMiddleware } from \"~/middleware/authMiddleware\";\nimport type { FileMeta } from \"~/models/file/FileMeta\";\nimport { FileMetaSchema } from \"~/models/file/FileMeta\";\n\nexport const GetFileMetasSchema = z.object({\n appName: z.string().min(1).max(255),\n subId: z.uuid(),\n});\n\nexport const FileSchema = z.object({\n appName: z.string().min(1).max(255),\n id: z.uuid(),\n});\n\nexport const UpdateFileMetaSchema = FileMetaSchema.extend({\n fileName: z.string().min(1).max(255),\n});\n\nconst DeleteFileSchema = FileSchema;\n\nconst BatchDeleteFilesSchema = GetFileMetasSchema;\n\nexport interface UploadFileResult {\n id: string;\n appName: string;\n subId: string;\n fileName: string;\n}\n\nexport const UploadFileMetaSchema = z.object({\n appName: z.string().min(1).max(255),\n subId: z.uuid(),\n file: z.instanceof(File),\n});\n\nexport const getFileMetas = createServerFn({ method: \"GET\" })\n .validator(GetFileMetasSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"subId\", data.subId);\n\n const { data: fileMetas } = await context.api.request<Array<FileMeta>>({\n url: `/v1/meta?${queryParams.toString()}`,\n method: \"GET\",\n });\n return fileMetas;\n });\n\nexport const getFileThumbnail = createServerFn({ method: \"GET\" })\n .validator(FileSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"id\", data.id);\n\n const response = await context.api.request<Readable>({\n url: `/v1/thumbnail?${queryParams.toString()}`,\n method: \"GET\",\n responseType: \"stream\",\n });\n\n setResponseHeaders(\n new Headers({\n \"Content-Type\": response.headers[\"content-type\"] as string,\n \"Cache-Control\": \"private, max-age=3600, immutable\",\n }),\n );\n return Readable.toWeb(response.data) as ReadableStream;\n });\n\nexport const getFile = createServerFn({ method: \"GET\" })\n .validator(FileSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"id\", data.id);\n\n const response = await context.api.request<Readable>({\n url: `/v1?${queryParams.toString()}`,\n method: \"GET\",\n responseType: \"stream\",\n });\n\n setResponseHeaders(\n new Headers({\n \"Content-Type\": response.headers[\"content-type\"] as string,\n \"Cache-Control\": \"private, max-age=3600, immutable\",\n }),\n );\n return Readable.toWeb(response.data) as ReadableStream;\n });\n\nexport const downloadFile = createServerFn({ method: \"GET\" })\n .validator(FileSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"id\", data.id);\n\n const response = await context.api.request<Readable>({\n url: `/v1/download?${queryParams.toString()}`,\n method: \"GET\",\n responseType: \"stream\",\n });\n\n setResponseHeaders(\n new Headers({\n \"Content-Type\": response.headers[\"content-type\"] as string,\n \"Cache-Control\": \"private, max-age=3600, immutable\",\n }),\n );\n return Readable.toWeb(response.data) as ReadableStream;\n });\n\nexport const updateFileMeta = createServerFn({ method: \"POST\" })\n .validator(UpdateFileMetaSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"id\", data.id);\n\n await context.api.request({ url: `/v1/meta?${queryParams.toString()}`, method: \"PUT\", data });\n });\n\nexport const deleteFile = createServerFn({ method: \"POST\" })\n .validator(DeleteFileSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"id\", data.id);\n\n await context.api.request({ url: `/v1?${queryParams.toString()}`, method: \"DELETE\" });\n });\n\nexport const batchDeleteFiles = createServerFn({ method: \"POST\" })\n .validator(BatchDeleteFilesSchema)\n .middleware([apiMiddleware({ baseURL: \"FILE_BASE_URL\", scopeKey: \"file\" })])\n .handler(async ({ data, context }) => {\n const queryParams = new URLSearchParams();\n queryParams.append(\"appName\", data.appName);\n queryParams.append(\"subId\", data.subId);\n\n await context.api.request({ url: `/v1?${queryParams.toString()}`, method: \"DELETE\" });\n });\n\nconst insecureHttpsAgent = new https.Agent({ rejectUnauthorized: false });\n\nexport const uploadFile = createServerFn({ method: \"POST\" })\n // File inputs must travel as multipart FormData — a File nested in a plain\n // payload object can't be seroval-serialized, so the request never fires.\n .validator((data: FormData) =>\n UploadFileMetaSchema.parse({\n appName: data.get(\"appName\"),\n subId: data.get(\"subId\"),\n file: data.get(\"file\"),\n }),\n )\n .middleware([authenticationMiddleware()])\n .handler(async ({ data }): Promise<UploadFileResult> => {\n // Prefer the signed-in user's delegated token so the file service stamps\n // createdBy; fall back to the app identity when there's no user session.\n let accessToken: string;\n try {\n accessToken = await getAccessToken(\"file\");\n } catch {\n accessToken = await getAppToken(\"file\");\n }\n // Stream instead of buffering the whole file: in-process callers (e.g. a File\n // from fs.openAsBlob) upload arbitrarily large files without holding them in RAM.\n const stream = Readable.fromWeb(data.file.stream() as import(\"node:stream/web\").ReadableStream);\n const id = uuidv7();\n const dotIndex = data.file.name.lastIndexOf(\".\");\n const fileExtension = dotIndex >= 0 ? data.file.name.slice(dotIndex + 1) : \"\";\n\n // Server-originated edge cases only — browser uploads go direct to the file\n // service via uploadFileMutationOptions (client) with the user's OBO token.\n await new Promise<void>((resolve, reject) => {\n const upload = new Upload(stream, {\n endpoint: `${serverEnv.FILE_BASE_URL}/v1/upload`,\n httpStack: new DefaultHttpStack({ agent: insecureHttpsAgent }),\n uploadSize: data.file.size,\n chunkSize: 1_048_576,\n metadata: {\n id,\n appName: data.appName,\n subId: data.subId,\n fileName: data.file.name,\n fileExtension,\n mimeType: data.file.type,\n },\n headers: { Authorization: `Bearer ${accessToken}` },\n onError: reject,\n onSuccess: () => resolve(),\n });\n upload.start();\n });\n\n return {\n id,\n appName: data.appName,\n subId: data.subId,\n fileName: data.file.name,\n };\n });\n"],"mappings":"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"}