mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-01 01:28:42 +09:00
## Summary - Add CLI project import support from synced `.webstudio/data.json` into another project via a destination share link. - Move project bundle import/export contract into `@webstudio-is/protocol`, including bundle versioning, staged upload constants, schema validation, and fixture coverage. - Upload project bundle data through staged TUS upload before calling the import RPC to avoid request body limits. - Upload referenced assets as binary files through the existing asset upload route before importing asset rows. - Add `--skip-assets` and `--ignore-version-check` import options. - Add retry handling for transient missing imported asset files by re-uploading only the reported missing assets. - Share missing-asset import error formatting/parsing through protocol to avoid duplicated string contracts. - Preserve browser asset upload behavior while adding API upload support. - Normalize schema naming across the branch to lower-case names without `Schema` suffix.
74 lines
1.7 KiB
TypeScript
74 lines
1.7 KiB
TypeScript
import { isRouteErrorResponse } from "@remix-run/react";
|
|
import { z } from "zod";
|
|
|
|
// Currently, we have multiple error formats, and not all of them are covered here.
|
|
// We should consolidate these formats into a single, unified format for consistency.
|
|
const pageError = z.union([
|
|
z.string().transform((message) => ({ message, description: undefined })),
|
|
z
|
|
.object({
|
|
message: z.string(),
|
|
details: z.string(),
|
|
hint: z.string().nullable(),
|
|
code: z.string(),
|
|
})
|
|
.transform(({ message, details, hint, code }) => ({
|
|
message,
|
|
description: `details: ${details}; hint: ${hint}; code: ${code}`,
|
|
})),
|
|
z.object({
|
|
message: z.string(),
|
|
description: z.string().optional(),
|
|
}),
|
|
]);
|
|
|
|
export const parseError = (
|
|
error: unknown
|
|
): {
|
|
status: number;
|
|
statusText?: string;
|
|
message: string;
|
|
description?: string;
|
|
} => {
|
|
if (error instanceof Error) {
|
|
return {
|
|
message: error.message,
|
|
status: 500,
|
|
};
|
|
}
|
|
|
|
if (isRouteErrorResponse(error)) {
|
|
const parsed = pageError.safeParse(error.data);
|
|
|
|
if (parsed.success) {
|
|
return {
|
|
message: parsed.data.message,
|
|
description: parsed.data.description,
|
|
status: error.status,
|
|
statusText: error.statusText,
|
|
};
|
|
}
|
|
|
|
return {
|
|
message: error.data ? JSON.stringify(error.data) : "unknown error",
|
|
status: error.status,
|
|
statusText: error.statusText,
|
|
};
|
|
}
|
|
|
|
const parsed = pageError.safeParse(error);
|
|
if (parsed.success) {
|
|
return {
|
|
message: parsed.data.message,
|
|
description: parsed.data.description,
|
|
status: 1001,
|
|
};
|
|
}
|
|
|
|
return {
|
|
message: JSON.stringify(error ?? "unknown error"),
|
|
status: 1001,
|
|
statusText: undefined,
|
|
};
|
|
};
|