chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,457 @@
import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit'
import { createLogger } from '@sim/logger'
import { getPostgresErrorCode, toError } from '@sim/utils/errors'
import {
bulkArchiveWorkspaceFileItems,
createWorkspaceFileFolder,
FileConflictError,
moveWorkspaceFileItems,
renameWorkspaceFile,
restoreWorkspaceFile,
restoreWorkspaceFileFolder,
updateWorkspaceFileFolder,
type WorkspaceFileArchiveResult,
WorkspaceFileFolderConflictError,
type WorkspaceFileFolderRecord,
WorkspaceFileItemsNotFoundError,
WorkspaceFileMoveConflictError,
type WorkspaceFileRecord,
} from '@/lib/uploads/contexts/workspace'
const logger = createLogger('WorkspaceFileFolderLifecycle')
export type WorkspaceFilesOrchestrationErrorCode =
| 'validation'
| 'not_found'
| 'conflict'
| 'internal'
export function workspaceFilesOrchestrationStatus(
errorCode: WorkspaceFilesOrchestrationErrorCode | undefined
): number {
if (errorCode === 'validation') return 400
if (errorCode === 'conflict') return 409
if (errorCode === 'not_found') return 404
return 500
}
export interface PerformDeleteWorkspaceFileItemsParams {
workspaceId: string
userId: string
fileIds?: string[]
folderIds?: string[]
}
export interface PerformDeleteWorkspaceFileItemsResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
deletedItems?: WorkspaceFileArchiveResult
}
export interface PerformMoveWorkspaceFileItemsParams {
workspaceId: string
userId: string
fileIds?: string[]
folderIds?: string[]
targetFolderId?: string | null
}
export interface PerformMoveWorkspaceFileItemsResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
movedItems?: { files: number; folders: number }
}
export interface PerformRenameWorkspaceFileParams {
workspaceId: string
fileId: string
name: string
userId: string
}
export interface PerformRenameWorkspaceFileResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
file?: WorkspaceFileRecord
}
export interface PerformRestoreWorkspaceFileParams {
workspaceId: string
fileId: string
userId: string
}
export interface PerformRestoreWorkspaceFileResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
}
export interface PerformCreateWorkspaceFileFolderParams {
workspaceId: string
userId: string
name: string
parentId?: string | null
}
export interface PerformCreateWorkspaceFileFolderResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
folder?: WorkspaceFileFolderRecord
}
export interface PerformUpdateWorkspaceFileFolderParams {
workspaceId: string
folderId: string
userId: string
name?: string
parentId?: string | null
sortOrder?: number
}
export interface PerformUpdateWorkspaceFileFolderResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
folder?: WorkspaceFileFolderRecord
}
export interface PerformRestoreWorkspaceFileFolderParams {
workspaceId: string
folderId: string
userId: string
}
export interface PerformRestoreWorkspaceFileFolderResult {
success: boolean
error?: string
errorCode?: WorkspaceFilesOrchestrationErrorCode
folder?: WorkspaceFileFolderRecord
restoredItems?: WorkspaceFileArchiveResult
}
export async function performDeleteWorkspaceFileItems(
params: PerformDeleteWorkspaceFileItemsParams
): Promise<PerformDeleteWorkspaceFileItemsResult> {
const { workspaceId, userId, fileIds = [], folderIds = [] } = params
if (fileIds.length === 0 && folderIds.length === 0) {
return {
success: false,
error: 'At least one file or folder must be selected',
errorCode: 'validation',
}
}
try {
const deletedItems = await bulkArchiveWorkspaceFileItems({ workspaceId, fileIds, folderIds })
if (fileIds.length === 1 && folderIds.length === 0 && deletedItems.files === 0) {
return { success: false, error: 'File not found', errorCode: 'not_found' }
}
if (folderIds.length === 1 && fileIds.length === 0 && deletedItems.folders === 0) {
return { success: false, error: 'Folder not found', errorCode: 'not_found' }
}
logger.info('Deleted workspace file items', {
workspaceId,
fileIds,
folderIds,
deletedItems,
})
if (fileIds.length > 0) {
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FILE_DELETED,
resourceType: AuditResourceType.FILE,
description: `Deleted ${fileIds.length} file${fileIds.length === 1 ? '' : 's'}`,
metadata: { fileIds },
})
}
if (folderIds.length > 0) {
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FOLDER_DELETED,
resourceType: AuditResourceType.FOLDER,
resourceId: folderIds.length === 1 ? folderIds[0] : undefined,
description: `Deleted ${folderIds.length} file folder${folderIds.length === 1 ? '' : 's'}`,
metadata: {
folderIds,
affected: {
files: deletedItems.files,
folders: deletedItems.folders,
},
},
})
}
return { success: true, deletedItems }
} catch (error) {
logger.error('Failed to delete workspace file items', { error })
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performMoveWorkspaceFileItems(
params: PerformMoveWorkspaceFileItemsParams
): Promise<PerformMoveWorkspaceFileItemsResult> {
const { workspaceId, userId, fileIds = [], folderIds = [], targetFolderId } = params
if (fileIds.length === 0 && folderIds.length === 0) {
return {
success: false,
error: 'At least one file or folder must be selected',
errorCode: 'validation',
}
}
try {
const moved = await moveWorkspaceFileItems({
workspaceId,
fileIds,
folderIds,
targetFolderId,
})
const movedItems = { files: moved.movedFiles, folders: moved.movedFolders }
logger.info('Moved workspace file items', {
workspaceId,
fileIds,
folderIds,
targetFolderId,
movedItems,
})
if (fileIds.length > 0) {
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FILE_MOVED,
resourceType: AuditResourceType.FILE,
description: `Moved ${fileIds.length} file${fileIds.length === 1 ? '' : 's'}${targetFolderId ? ' to folder' : ' to root'}`,
metadata: { fileIds, targetFolderId },
})
}
if (folderIds.length > 0) {
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FOLDER_MOVED,
resourceType: AuditResourceType.FOLDER,
resourceId: folderIds.length === 1 ? folderIds[0] : undefined,
description: `Moved ${folderIds.length} file folder${folderIds.length === 1 ? '' : 's'}${targetFolderId ? ' to folder' : ' to root'}`,
metadata: { folderIds, targetFolderId },
})
}
return { success: true, movedItems }
} catch (error) {
logger.error('Failed to move workspace file items', { error })
if (
error instanceof WorkspaceFileMoveConflictError ||
error instanceof WorkspaceFileFolderConflictError ||
getPostgresErrorCode(error) === '23505'
) {
return {
success: false,
error:
error instanceof Error
? error.message
: 'A file or folder with this name already exists in the destination folder',
errorCode: 'conflict',
}
}
if (error instanceof WorkspaceFileItemsNotFoundError) {
return { success: false, error: error.message, errorCode: 'not_found' }
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performRenameWorkspaceFile(
params: PerformRenameWorkspaceFileParams
): Promise<PerformRenameWorkspaceFileResult> {
const { workspaceId, fileId, name, userId } = params
try {
const file = await renameWorkspaceFile(workspaceId, fileId, name)
logger.info('Renamed workspace file', { workspaceId, fileId, name: file.name })
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FILE_UPDATED,
resourceType: AuditResourceType.FILE,
resourceId: fileId,
resourceName: file.name,
description: `Renamed file to "${file.name}"`,
})
return { success: true, file }
} catch (error) {
logger.error('Failed to rename workspace file', { error })
if (error instanceof FileConflictError || getPostgresErrorCode(error) === '23505') {
return { success: false, error: toError(error).message, errorCode: 'conflict' }
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performRestoreWorkspaceFile(
params: PerformRestoreWorkspaceFileParams
): Promise<PerformRestoreWorkspaceFileResult> {
const { workspaceId, fileId, userId } = params
try {
await restoreWorkspaceFile(workspaceId, fileId)
logger.info('Restored workspace file', { workspaceId, fileId })
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FILE_RESTORED,
resourceType: AuditResourceType.FILE,
resourceId: fileId,
resourceName: fileId,
description: `Restored workspace file ${fileId}`,
})
return { success: true }
} catch (error) {
logger.error('Failed to restore workspace file', { error })
if (error instanceof FileConflictError || getPostgresErrorCode(error) === '23505') {
return { success: false, error: toError(error).message, errorCode: 'conflict' }
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performCreateWorkspaceFileFolder(
params: PerformCreateWorkspaceFileFolderParams
): Promise<PerformCreateWorkspaceFileFolderResult> {
const { workspaceId, userId, name, parentId } = params
try {
const folder = await createWorkspaceFileFolder({ workspaceId, userId, name, parentId })
logger.info('Created workspace file folder', { workspaceId, folderId: folder.id })
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FOLDER_CREATED,
resourceType: AuditResourceType.FOLDER,
resourceId: folder.id,
resourceName: folder.name,
description: `Created file folder "${folder.name}"`,
})
return { success: true, folder }
} catch (error) {
logger.error('Failed to create workspace file folder', { error })
if (
error instanceof WorkspaceFileFolderConflictError ||
getPostgresErrorCode(error) === '23505'
) {
return { success: false, error: toError(error).message, errorCode: 'conflict' }
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performUpdateWorkspaceFileFolder(
params: PerformUpdateWorkspaceFileFolderParams
): Promise<PerformUpdateWorkspaceFileFolderResult> {
const { workspaceId, folderId, userId, name, parentId, sortOrder } = params
try {
const folder = await updateWorkspaceFileFolder({
workspaceId,
folderId,
name,
parentId,
sortOrder,
})
logger.info('Updated workspace file folder', { workspaceId, folderId })
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FOLDER_UPDATED,
resourceType: AuditResourceType.FOLDER,
resourceId: folderId,
resourceName: folder.name,
description: `Updated file folder "${folder.name}"`,
})
return { success: true, folder }
} catch (error) {
logger.error('Failed to update workspace file folder', { error })
if (
error instanceof WorkspaceFileFolderConflictError ||
getPostgresErrorCode(error) === '23505'
) {
return {
success: false,
error:
getPostgresErrorCode(error) === '23505'
? 'A folder with this name already exists in this location'
: toError(error).message,
errorCode: 'conflict',
}
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
export async function performRestoreWorkspaceFileFolder(
params: PerformRestoreWorkspaceFileFolderParams
): Promise<PerformRestoreWorkspaceFileFolderResult> {
const { workspaceId, folderId, userId } = params
try {
const { folder, restoredItems } = await restoreWorkspaceFileFolder(workspaceId, folderId)
logger.info('Restored workspace file folder', { workspaceId, folderId, restoredItems })
recordAudit({
workspaceId,
actorId: userId,
action: AuditAction.FOLDER_RESTORED,
resourceType: AuditResourceType.FOLDER,
resourceId: folderId,
resourceName: folder.name,
description: `Restored file folder "${folder.name}"`,
metadata: {
affected: {
files: restoredItems.files,
subfolders: Math.max(0, restoredItems.folders - 1),
},
},
})
return { success: true, folder, restoredItems }
} catch (error) {
logger.error('Failed to restore workspace file folder', { error })
if (getPostgresErrorCode(error) === '23505') {
return {
success: false,
error: 'A folder with this name already exists in this location',
errorCode: 'conflict',
}
}
return { success: false, error: toError(error).message, errorCode: 'internal' }
}
}
@@ -0,0 +1,25 @@
export {
type PerformCreateWorkspaceFileFolderParams,
type PerformCreateWorkspaceFileFolderResult,
type PerformDeleteWorkspaceFileItemsParams,
type PerformDeleteWorkspaceFileItemsResult,
type PerformMoveWorkspaceFileItemsParams,
type PerformMoveWorkspaceFileItemsResult,
type PerformRenameWorkspaceFileParams,
type PerformRenameWorkspaceFileResult,
type PerformRestoreWorkspaceFileFolderParams,
type PerformRestoreWorkspaceFileFolderResult,
type PerformRestoreWorkspaceFileParams,
type PerformRestoreWorkspaceFileResult,
type PerformUpdateWorkspaceFileFolderParams,
type PerformUpdateWorkspaceFileFolderResult,
performCreateWorkspaceFileFolder,
performDeleteWorkspaceFileItems,
performMoveWorkspaceFileItems,
performRenameWorkspaceFile,
performRestoreWorkspaceFile,
performRestoreWorkspaceFileFolder,
performUpdateWorkspaceFileFolder,
type WorkspaceFilesOrchestrationErrorCode,
workspaceFilesOrchestrationStatus,
} from './file-folder-lifecycle'