= {
+ pptx: 'text/x-pptxgenjs',
+ docx: 'text/x-docxjs',
+ pdf: 'text/x-pdflibjs',
+}
+
+export function isTextEditable(file: { type: string; name: string }): boolean {
+ return resolveFileCategory(file.type, file.name) === 'text-editable'
+}
+
+export function isPreviewable(file: { type: string; name: string }): boolean {
+ return resolvePreviewType(file.type, file.name) !== null
+}
+
+/**
+ * Markdown files render in the inline rich editor ({@link RichMarkdownEditor}) rather than
+ * the raw Monaco editor. Toolbars use this to hide the raw/split/preview mode controls,
+ * which don't apply to the single-surface editor.
+ */
+export function isMarkdownFile(file: { type: string; name: string }): boolean {
+ return resolvePreviewType(file.type, file.name) === 'markdown'
+}
+
+/**
+ * A CSV larger than {@link CSV_INLINE_EDIT_MAX_BYTES} is shown as a streamed, read-only preview —
+ * the editor would OOM loading the whole file. The viewer renders {@link CsvTablePreview} for it,
+ * and toolbars use this to hide the edit/split/save controls (there is no editor to switch to).
+ */
+export function isCsvStreamOnly(file: {
+ type: string | null
+ name: string
+ size?: number | null
+}): boolean {
+ return (
+ resolvePreviewType(file.type, file.name) === 'csv' &&
+ (file.size ?? 0) > CSV_INLINE_EDIT_MAX_BYTES
+ )
+}
+
+export type PreviewMode = 'editor' | 'split' | 'preview'
+
+/**
+ * Live agent output for the file on screen. One optional object rather than five
+ * loose props, because they are only ever set together and only this view has
+ * them — no other resource streams.
+ */
+export interface FileViewStreaming {
+ /** The text streamed so far, or `undefined` once the stream settles. */
+ content?: string
+ /** The agent holds the write lock: the surface stays read-only even after the stream ends. */
+ isAgentEditing?: boolean
+ /**
+ * True when the stream delivers complete full-file snapshots (an `append`/`patch` edit built on
+ * the existing file) rather than a from-scratch rebuild (`create`/`update`). Incremental
+ * snapshots are applied live; a rebuild is only revealed while it extends what is shown.
+ */
+ isIncremental?: boolean
+ /**
+ * The agent edit operation driving the stream, when known
+ * (`create`/`append`/`update`/`patch`). In the collaborative path it decides only
+ * whether to stream mid-flight: an `update` (from-scratch rewrite) is HELD until
+ * settle so the open doc doesn't collapse to a partial result, while
+ * `append`/`patch`/`create` apply each frame.
+ */
+ operation?: string
+ disableAutoScroll?: boolean
+ /** Remounts the editor when the agent starts a new turn against the same file. */
+ contextKey?: string
+ /**
+ * Name of a file the agent is creating that has no record yet. The renderer is
+ * chosen from it and the surface holds only the streamed text — there are no
+ * bytes to fetch until the agent's write lands.
+ */
+ fileName?: string
+}
+
+export interface FileViewProps {
+ source: ResourceSource<'file'>
+ grants: ResourceGrants
+ host: ResourceHost
+ /**
+ * Render a reading surface with no editor at all: text files render through
+ * {@link PreviewPanel} (or a plain ``) rather than a disabled
+ * {@link TextEditor}.
+ *
+ * Not derivable from `grants.write` — a workspace member who cannot edit still
+ * gets the full editor chrome (syntax highlighting, split preview) on the Files
+ * page, while an embedded or shared file is a reading surface for everyone.
+ */
+ readOnly?: boolean
+ previewMode?: PreviewMode
+ autoFocus?: boolean
+ onDirtyChange?: (isDirty: boolean) => void
+ onSaveStatusChange?: (
+ status: 'idle' | 'saving' | 'saved' | 'error',
+ retry?: () => Promise
+ ) => void
+ saveRef?: React.MutableRefObject<(() => Promise) | null>
+ discardRef?: React.MutableRefObject<(() => void) | null>
+ streaming?: FileViewStreaming
+ /**
+ * Opt this surface into live collaborative editing (markdown files only). Set by the
+ * Files page and the embedded chat file preview; other hosts leave it off so
+ * collaboration and agent-streaming never target one editor.
+ */
+ collaborative?: boolean
+ /**
+ * Called (debounced) with the markdown document's leading-heading text while the file
+ * is still untitled, so the caller can name the file after it. Only wired for the
+ * editable markdown editor.
+ */
+ onDeriveTitleFromHeading?: (headingText: string) => void
+ /**
+ * How this host moves the viewer — the router half of `host`. Supplied by a
+ * host that owns a router (`router.push`); omitted by a `'public'` one, where
+ * mentions and in-document links resolve to `null` anyway and stay inert.
+ */
+ onNavigate?: (path: string) => void
+}
+
+/** The record for a file an agent is writing that does not exist yet. */
+function streamingFileRecord(fileName: string): FileViewRecord {
+ const extension = getFileExtension(fileName)
+ return {
+ id: 'streaming-file',
+ name: fileName,
+ type: GENERATED_SOURCE_MIME_BY_EXTENSION[extension] ?? getMimeTypeFromExtension(extension),
+ key: '',
+ size: 0,
+ updatedAt: new Date(0),
+ folderId: null,
+ }
+}
+
+/**
+ * Renders one file's real contents — PDFs, images, docx, xlsx, pptx, markdown,
+ * CSV, and code — from whichever address its {@link ResourceSource} carries, so
+ * the same view serves the Files page, an embedded panel, and an anonymous share.
+ */
+export function FileView({ source, grants, host, onNavigate, ...props }: FileViewProps) {
+ const shared = useMemo(() => (source.via === 'share' ? shareFileRecord(source) : null), [source])
+ const streamingName = props.streaming?.fileName
+ const streaming = useMemo(
+ () => (streamingName ? streamingFileRecord(streamingName) : null),
+ [streamingName]
+ )
+ /**
+ * Both of these describe the file without a lookup — a share carries its
+ * server-resolved seed, and an agent-written file exists only in the stream.
+ * Resolving them here keeps {@link WorkspaceFileView}, and therefore the
+ * workspace record query, off the page entirely when neither address applies.
+ */
+ const known = shared ?? streaming
+
+ return (
+
+ {known ? : }
+
+ )
+}
+
+type FileViewSurfaceProps = Omit
+
+/**
+ * Resolves the workspace record for the addressed file. The record comes from the
+ * shared active-files query, so a surface that already listed the workspace's
+ * files reads it straight from cache.
+ */
+function WorkspaceFileView(props: FileViewSurfaceProps) {
+ const { source, host } = useResourceOfKind('file')
+ const workspaceId = fileWorkspaceId(source) ?? ''
+ const fileId = source.via === 'workspace' ? source.resourceId : ''
+ const { data, isPending, isFetching, isError } = useWorkspaceFileRecord(workspaceId, fileId)
+ const record = data ?? null
+
+ /**
+ * A background refetch that has not yet produced the record still reads as
+ * pending — a file created moments ago must not flash "not found" while the
+ * invalidated list is in flight.
+ */
+ if (isPending || (isFetching && !record)) {
+ return
+ }
+
+ if (!record) {
+ /**
+ * A failed lookup is not a missing file. Reporting an outage as a deletion
+ * sends the viewer off to re-wire something that is still perfectly valid.
+ */
+ const reason: UnavailableReason = isError ? 'transient' : 'missing'
+ return (
+
+ )
+ }
+
+ return
+}
+
+function FileViewContent({
+ file,
+ readOnly = false,
+ previewMode,
+ autoFocus,
+ onDirtyChange,
+ onSaveStatusChange,
+ saveRef,
+ discardRef,
+ streaming,
+ collaborative,
+ onDeriveTitleFromHeading,
+}: FileViewSurfaceProps & { file: FileViewRecord }) {
+ const { source, grants } = useResourceOfKind('file')
+ const canEdit = grants.write
+ const category = resolveFileCategory(file.type, file.name)
+
+ if (category === 'text-editable') {
+ if (readOnly) {
+ // ReadOnlyTextPreview loads the whole file as text; a large CSV would OOM the
+ // browser. CsvTablePreview's streamed fallback is workspace-only, so on the
+ // read-only path a large CSV is download-only.
+ if (isCsvStreamOnly(file)) {
+ return
+ }
+ // Markdown renders through the inline rich editor (non-editable) so a shared or
+ // embedded file matches the in-app reading experience; canEdit={false} disables
+ // autosave, the bubble menu, and every other editing affordance.
+ if (isMarkdownFile(file)) {
+ return
+ }
+ return
+ }
+ // A large CSV can't be loaded whole into the editor (the browser OOMs on the full text).
+ // Render a streamed, read-only preview of the first rows + an "Import as a table" path
+ // instead. That route is workspace-authenticated, so a share falls back to download-only.
+ if (isCsvStreamOnly(file)) {
+ return fileWorkspaceId(source) ? (
+
+ ) : (
+
+ )
+ }
+
+ if (isMarkdownFile(file)) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+ }
+
+ if (category === 'iframe-previewable') {
+ return
+ }
+
+ if (category === 'image-previewable') {
+ return
+ }
+
+ if (category === 'audio-previewable') {
+ return
+ }
+
+ if (category === 'video-previewable') {
+ return
+ }
+
+ if (category === 'docx-previewable') {
+ return
+ }
+
+ if (category === 'pptx-previewable') {
+ return
+ }
+
+ if (category === 'xlsx-previewable') {
+ return
+ }
+
+ return
+}
+
+/**
+ * Read-only text/markdown/code preview. Renders rich types (markdown, csv, svg,
+ * mermaid, html) through {@link PreviewPanel} and plain text/code in a ``.
+ * Fetches content through the mounted source, so it works for both workspace
+ * files and public share links.
+ */
+const ReadOnlyTextPreview = memo(function ReadOnlyTextPreview({ file }: { file: FileViewRecord }) {
+ const { source } = useResourceOfKind('file')
+ const { data: content, isLoading, error } = useWorkspaceFileContent(source, file.id, file.key)
+
+ const resolvedError = resolvePreviewError((error as Error | null) ?? null, null)
+ if (resolvedError) return
+ if (isLoading || content == null) return
+
+ if (resolvePreviewType(file.type, file.name)) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+})
+
+const IframePreview = memo(function IframePreview({ file }: { file: FileViewRecord }) {
+ const preview = useDocPreviewBinary(file)
+
+ const bufferSource = useMemo(
+ () => (preview.data ? { kind: 'buffer', buffer: preview.data } : null),
+ [preview.data]
+ )
+
+ const error = resolvePreviewError(preview.error, null)
+ if (error) return
+
+ if (!bufferSource) {
+ return {PREVIEW_LOADING_OVERLAY}
+ }
+
+ return (
+
+
+
+ )
+})
+
+/**
+ * Audio and video, played straight from the content URL.
+ *
+ * Deliberately NOT fetched: the element streams the object itself, so playback
+ * starts on the first bytes and a seek costs one short ranged request. The
+ * previous implementation downloaded the whole file and played it from a
+ * `blob:` URL — the only reason the scrubber worked, since the routes advertised
+ * no `Accept-Ranges` — which put an entire video in the JS heap before the first
+ * frame. The routes byte-serve now, so the element does this correctly and for
+ * free.
+ *
+ * `preload='metadata'` fetches only enough to know the duration, so mounting a
+ * long video costs one small request rather than a buffer.
+ */
+const MediaPreview = memo(function MediaPreview({
+ file,
+ kind,
+}: {
+ file: FileViewRecord
+ kind: 'audio' | 'video'
+}) {
+ const { source } = useResourceOfKind('file')
+ const [failed, setFailed] = useState(false)
+
+ /** Versioned so an edited file busts the browser's media cache. */
+ const src = file.key
+ ? fileContentUrl(source, file.key, { version: file.updatedAt.getTime() })
+ : null
+
+ if (!src || failed) {
+ return
+ }
+
+ if (kind === 'audio') {
+ return (
+
+
+ {/* biome-ignore lint/a11y/useMediaCaption: audio from workspace files */}
+
setFailed(true)}
+ className='w-full max-w-[480px]'
+ />
+
+ )
+ }
+
+ /**
+ * The element fills the pane and letterboxes the frame, rather than sizing
+ * itself to the video.
+ *
+ * A `` reports an intrinsic 300x150 until its metadata arrives, so
+ * `max-h-full max-w-full` — which sizes *to* the intrinsics — paints a small
+ * box and snaps to full size once the first bytes land. Driving the box from
+ * the pane instead makes the layout independent of load state, and
+ * `object-contain` keeps the aspect ratio honest inside it.
+ */
+ return (
+
+ {/* biome-ignore lint/a11y/useMediaCaption: video from workspace files */}
+ setFailed(true)}
+ className='h-full w-full object-contain'
+ />
+
+ )
+})
+
+/**
+ * The dead end for a file no renderer handles — an archive, an installer, a
+ * columnar dataset. It carries its own download link rather than pointing at a
+ * button in the surrounding chrome: this view is mounted on surfaces that draw
+ * no chrome at all (the fullscreen file route, an interface's file module), and
+ * telling a visitor to press a button that is not on the page strands them with
+ * no way to reach the bytes.
+ */
+const UnsupportedPreview = memo(function UnsupportedPreview({ file }: { file: FileViewRecord }) {
+ const { source } = useResourceOfKind('file')
+ const ext = getFileExtension(file.name)
+ const href = file.key
+ ? fileContentUrl(source, file.key, { version: file.updatedAt.getTime() })
+ : null
+
+ return (
+
+
+ Preview not available{ext ? ` for .${ext} files` : ' for this file'}
+
+ {href ? (
+
+ Download
+
+ ) : (
+
This file has no content yet
+ )}
+
+ )
+})
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-import.ts b/apps/sim/components/resources/file-view/hooks/csv-import.ts
similarity index 91%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-import.ts
rename to apps/sim/components/resources/file-view/hooks/csv-import.ts
index b91d1b99318..e0daa8bab99 100644
--- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-import.ts
+++ b/apps/sim/components/resources/file-view/hooks/csv-import.ts
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useRef } from 'react'
import { toast } from '@sim/emcn'
import { generateId } from '@sim/utils/id'
-import { useRouter } from 'next/navigation'
+import { useResource } from '@/components/resources/resource-provider'
import { CSV_PREVIEW_MAX_ROWS } from '@/lib/api/contracts/workspace-file-table'
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
import { useImportFileAsTable } from '@/hooks/queries/tables'
@@ -22,7 +22,7 @@ export function useCsvTruncationImport(
truncated: boolean,
readOnly = false
) {
- const router = useRouter()
+ const { navigate } = useResource()
const importFile = useImportFileAsTable()
// Guards against a double-tap on the toast action kicking off two parallel imports of the same
@@ -40,7 +40,7 @@ export function useCsvTruncationImport(
description: 'This runs in the background.',
action: {
label: 'View tables',
- onClick: () => router.push(`/workspace/${workspaceId}/tables`),
+ onClick: () => navigate(`/workspace/${workspaceId}/tables`),
},
})
importFile.mutate(
@@ -52,7 +52,7 @@ export function useCsvTruncationImport(
},
}
)
- // importFile.mutate and router are stable references
+ // importFile.mutate and navigate are stable references
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [workspaceId, file.key, file.name])
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-doc-preview-binary.test.ts b/apps/sim/components/resources/file-view/hooks/use-doc-preview-binary.test.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-doc-preview-binary.test.ts
rename to apps/sim/components/resources/file-view/hooks/use-doc-preview-binary.test.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-doc-preview-binary.ts b/apps/sim/components/resources/file-view/hooks/use-doc-preview-binary.ts
similarity index 92%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-doc-preview-binary.ts
rename to apps/sim/components/resources/file-view/hooks/use-doc-preview-binary.ts
index 5819182db44..f8e2e0e3afa 100644
--- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-doc-preview-binary.ts
+++ b/apps/sim/components/resources/file-view/hooks/use-doc-preview-binary.ts
@@ -1,8 +1,9 @@
'use client'
import { useRef } from 'react'
-import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
+import { useResourceOfKind } from '@/components/resources/resource-provider'
import { useWorkspaceFileBinary } from '@/hooks/queries/workspace-files'
+import type { FileViewRecord } from '@/resources/file-source'
export type DocPreviewState = 'empty' | 'loading' | 'ready' | 'stale'
@@ -13,7 +14,7 @@ export interface DocPreviewBinary {
dataUpdatedAt: number
}
-type DocPreviewFile = Pick
+type DocPreviewFile = Pick
interface ResolveDocPreviewArgs {
data: ArrayBuffer | undefined
@@ -126,8 +127,9 @@ export function stepDocPreviewBinary({
* placeholder (which still holds the prior file's bytes) is ignored until a fresh
* binary resolves for the new file, so one viewer never renders another file's content.
*/
-export function useDocPreviewBinary(workspaceId: string, file: DocPreviewFile): DocPreviewBinary {
- const query = useWorkspaceFileBinary(workspaceId, file.id, file.key, {
+export function useDocPreviewBinary(file: DocPreviewFile): DocPreviewBinary {
+ const { source } = useResourceOfKind('file')
+ const query = useWorkspaceFileBinary(source, file.id, file.key, {
enabled: (file.size ?? 0) > 0,
version: Number(new Date(file.updatedAt)) || file.size,
})
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.test.tsx b/apps/sim/components/resources/file-view/hooks/use-editable-file-content.test.tsx
similarity index 91%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.test.tsx
rename to apps/sim/components/resources/file-view/hooks/use-editable-file-content.test.tsx
index 58c5447df66..0e34c389b06 100644
--- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.test.tsx
+++ b/apps/sim/components/resources/file-view/hooks/use-editable-file-content.test.tsx
@@ -23,7 +23,7 @@ const { queryState } = vi.hoisted(() => ({
vi.mock('@/hooks/queries/workspace-files', () => ({
useWorkspaceFileContent: (
- _workspaceId: string,
+ _source: unknown,
_fileId: string,
_key: string,
_raw?: boolean,
@@ -41,6 +41,8 @@ vi.mock('idb-keyval', () => ({
del: vi.fn(async () => {}),
}))
+import { ResourceProvider } from '@/components/resources/resource-provider'
+import { grantsFromPermissions, workspaceSource } from '@/resources'
import {
RECONCILING_REFETCH_INTERVAL_MS,
RECONCILING_REFETCH_SLOW_INTERVAL_MS,
@@ -48,6 +50,9 @@ import {
useEditableFileContent,
} from './use-editable-file-content'
+const SOURCE = workspaceSource({ kind: 'file', workspaceId: 'ws-1', resourceId: 'f1' })
+const GRANTS = grantsFromPermissions({ canRead: true, canEdit: true, canAdmin: false })
+
const FILE = {
id: 'f1',
key: 'workspace/ws-1/123-abc-doc.md',
@@ -68,7 +73,6 @@ let latest: ReturnType | null = null
function Probe(props: ProbeProps) {
latest = useEditableFileContent({
file: FILE,
- workspaceId: 'ws-1',
canEdit: true,
streamingContent: props.streamingContent,
isAgentEditing: props.isAgentEditing,
@@ -76,9 +80,17 @@ function Probe(props: ProbeProps) {
return null
}
+function MountedProbe(props: ProbeProps) {
+ return (
+
+
+
+ )
+}
+
function render(props: ProbeProps) {
act(() => {
- root?.render( )
+ root?.render( )
})
}
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.ts b/apps/sim/components/resources/file-view/hooks/use-editable-file-content.ts
similarity index 95%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.ts
rename to apps/sim/components/resources/file-view/hooks/use-editable-file-content.ts
index f8dac76bbdd..a6f9aca33ea 100644
--- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-editable-file-content.ts
+++ b/apps/sim/components/resources/file-view/hooks/use-editable-file-content.ts
@@ -2,7 +2,12 @@
import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'
import { toast } from '@sim/emcn'
-import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
+import {
+ INITIAL_TEXT_EDITOR_CONTENT_STATE,
+ type SyncTextEditorContentStateOptions,
+ textEditorContentReducer,
+} from '@/components/resources/file-view/utils/text-editor-state'
+import { useResourceOfKind } from '@/components/resources/resource-provider'
import { GENERATED_DOCUMENT_SOURCE_TYPES } from '@/lib/uploads/utils/file-utils'
import {
useUpdateWorkspaceFileContent,
@@ -10,11 +15,7 @@ import {
} from '@/hooks/queries/workspace-files'
import { type SaveStatus, useAutosave } from '@/hooks/use-autosave'
import { useSmoothText } from '@/hooks/use-smooth-text'
-import {
- INITIAL_TEXT_EDITOR_CONTENT_STATE,
- type SyncTextEditorContentStateOptions,
- textEditorContentReducer,
-} from './text-editor-state'
+import { type FileViewRecord, fileWorkspaceId } from '@/resources/file-source'
/**
* Generated-document source files (`.pptx`/`.docx`/`.pdf`/`.xlsx` builders) whose
@@ -43,8 +44,7 @@ export const RECONCILING_REFETCH_WINDOW_MS = 45_000
export const RECONCILING_REFETCH_SLOW_INTERVAL_MS = 15_000
interface UseEditableFileContentOptions {
- file: WorkspaceFileRecord
- workspaceId: string
+ file: FileViewRecord
canEdit: boolean
streamingContent?: string
isAgentEditing?: boolean
@@ -134,7 +134,6 @@ function useFileContentState(options: SyncTextEditorContentStateOptions) {
*/
export function useEditableFileContent({
file,
- workspaceId,
canEdit,
streamingContent,
isAgentEditing,
@@ -145,6 +144,9 @@ export function useEditableFileContent({
normalizeBaseline,
canAutosave = true,
}: UseEditableFileContentOptions): EditableFileContent {
+ const { source } = useResourceOfKind('file')
+ /** `null` on a share: there is nothing to save to, and `canEdit` is already false there. */
+ const workspaceId = fileWorkspaceId(source)
const onDirtyChangeRef = useRef(onDirtyChange)
const onSaveStatusChangeRef = useRef(onSaveStatusChange)
onDirtyChangeRef.current = onDirtyChange
@@ -174,7 +176,7 @@ export function useEditableFileContent({
isLoading,
error,
} = useWorkspaceFileContent(
- workspaceId,
+ source,
file.id,
file.key,
GENERATED_SOURCE_FILE_TYPES.has(file.type),
@@ -235,6 +237,7 @@ export function useEditableFileContent({
const onSave = useCallback(
async (overrideContent?: string) => {
+ if (!workspaceId) return
const next = overrideContent ?? contentRef.current
await updateContentRef.current.mutateAsync({ workspaceId, fileId: file.id, content: next })
markSavedContent(next)
@@ -242,7 +245,8 @@ export function useEditableFileContent({
[workspaceId, file.id, markSavedContent]
)
- const autosaveEnabled = canEdit && isInitialized && !isStreamInteractionLocked && canAutosave
+ const autosaveEnabled =
+ Boolean(workspaceId) && canEdit && isInitialized && !isStreamInteractionLocked && canAutosave
const { saveStatus, saveImmediately, isDirty, discard } = useAutosave({
content,
diff --git a/apps/sim/components/resources/file-view/index.ts b/apps/sim/components/resources/file-view/index.ts
new file mode 100644
index 00000000000..9ac199ae97c
--- /dev/null
+++ b/apps/sim/components/resources/file-view/index.ts
@@ -0,0 +1,16 @@
+/**
+ * The file resource view. Consumers mount {@link FileView} against a source,
+ * grants, and a host; everything else here is what the surrounding surfaces
+ * (toolbars, tab chrome) need to describe a file without opening it.
+ */
+
+export { RICH_PREVIEWABLE_EXTENSIONS } from './components/preview-panel'
+export type { FileViewStreaming, PreviewMode } from './file-view'
+export {
+ FileView,
+ isCsvStreamOnly,
+ isMarkdownFile,
+ isPreviewable,
+ isTextEditable,
+} from './file-view'
+export { resolveFileCategory } from './utils/file-category'
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-category.test.ts b/apps/sim/components/resources/file-view/utils/file-category.test.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-category.test.ts
rename to apps/sim/components/resources/file-view/utils/file-category.test.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-category.ts b/apps/sim/components/resources/file-view/utils/file-category.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-category.ts
rename to apps/sim/components/resources/file-view/utils/file-category.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts b/apps/sim/components/resources/file-view/utils/preview-wheel-zoom.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts
rename to apps/sim/components/resources/file-view/utils/preview-wheel-zoom.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/text-editor-state.test.ts b/apps/sim/components/resources/file-view/utils/text-editor-state.test.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/text-editor-state.test.ts
rename to apps/sim/components/resources/file-view/utils/text-editor-state.test.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/text-editor-state.ts b/apps/sim/components/resources/file-view/utils/text-editor-state.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/text-editor-state.ts
rename to apps/sim/components/resources/file-view/utils/text-editor-state.ts
diff --git a/apps/sim/components/resources/resource-empty-state/index.ts b/apps/sim/components/resources/resource-empty-state/index.ts
new file mode 100644
index 00000000000..dc7ff87381f
--- /dev/null
+++ b/apps/sim/components/resources/resource-empty-state/index.ts
@@ -0,0 +1,2 @@
+export type { ResourceEmptyStateProps } from '@/components/resources/resource-empty-state/resource-empty-state'
+export { ResourceEmptyState } from '@/components/resources/resource-empty-state/resource-empty-state'
diff --git a/apps/sim/components/resources/resource-empty-state/resource-empty-state.tsx b/apps/sim/components/resources/resource-empty-state/resource-empty-state.tsx
new file mode 100644
index 00000000000..1807beed5aa
--- /dev/null
+++ b/apps/sim/components/resources/resource-empty-state/resource-empty-state.tsx
@@ -0,0 +1,42 @@
+import type { ComponentType } from 'react'
+
+export interface ResourceEmptyStateProps {
+ icon: ComponentType<{ className?: string }>
+ /**
+ * The headline, when this fills a whole view — "File not found", "Couldn't
+ * load scheduled task". Omit it inside a cell that already has a title bar:
+ * a titled state is a page telling you why it is blank, an untitled one is a
+ * placeholder inside a frame that is already labelled.
+ */
+ title?: string
+ /** The one sentence explaining the state. Always present. */
+ description: string
+}
+
+/**
+ * The placeholder every resource view falls back to — nothing configured, a
+ * reference to something since deleted, no access, or an empty result.
+ *
+ * It draws its **interior only** and fills its parent: the frame (border,
+ * radius, selection ring, title bar) belongs to whatever mounted it.
+ */
+export function ResourceEmptyState({ icon: Icon, title, description }: ResourceEmptyStateProps) {
+ if (!title) {
+ return (
+
+ )
+ }
+
+ return (
+
+
+
+
{title}
+
{description}
+
+
+ )
+}
diff --git a/apps/sim/components/resources/resource-provider/index.ts b/apps/sim/components/resources/resource-provider/index.ts
new file mode 100644
index 00000000000..c5c178e0350
--- /dev/null
+++ b/apps/sim/components/resources/resource-provider/index.ts
@@ -0,0 +1,11 @@
+export type {
+ ResourceContextValue,
+ ResourceProviderProps,
+} from '@/components/resources/resource-provider/resource-provider'
+export {
+ ResourceProvider,
+ useOptionalResource,
+ useOptionalResourceOfKind,
+ useResource,
+ useResourceOfKind,
+} from '@/components/resources/resource-provider/resource-provider'
diff --git a/apps/sim/components/resources/resource-provider/resource-provider.tsx b/apps/sim/components/resources/resource-provider/resource-provider.tsx
new file mode 100644
index 00000000000..be92d0e56eb
--- /dev/null
+++ b/apps/sim/components/resources/resource-provider/resource-provider.tsx
@@ -0,0 +1,116 @@
+'use client'
+
+import { createContext, type ReactNode, useContext, useMemo } from 'react'
+import type { ResourceGrants, ResourceHost, ResourceKind, ResourceSource } from '@/resources'
+
+/** The three axes, resolved once by whoever mounts a resource view. */
+export interface ResourceContextValue {
+ readonly source: ResourceSource
+ readonly grants: ResourceGrants
+ readonly host: ResourceHost
+ /**
+ * Sends the viewer to an in-app path — the router half of {@link ResourceHost}.
+ *
+ * Targets come from `source.hrefFor`; this only performs the move, and only
+ * because a unit must never hold a router of its own: `useRouter()` inside a
+ * view silently assumes it is mounted under a workspace route, which is true
+ * in exactly two of the three hosts. A `'public'` host supplies nothing, so
+ * navigation is inert there by construction rather than by a check at every
+ * call site.
+ */
+ readonly navigate: (path: string) => void
+}
+
+/** A host that owns no router. Module scope, so the context value stays stable. */
+function noNavigation(): void {}
+
+/**
+ * Deliberately has no default that silently works. A default would let a
+ * renderer mounted outside a provider resolve one context's URLs while
+ * rendering in the other's — the exact failure this seam exists to make
+ * impossible — so the absence is a thrown error instead.
+ */
+const ResourceContext = createContext(null)
+
+export interface ResourceProviderProps
+ extends Omit, 'navigate'> {
+ children: ReactNode
+ /**
+ * How this host moves the viewer. Omit it when the host owns no router — a
+ * public share has no workspace route to send anyone to.
+ *
+ * Pass a stable reference (`router.push`, or a `useCallback`); an inline
+ * arrow re-creates the context value on every render of the host.
+ */
+ onNavigate?: (path: string) => void
+}
+
+export function ResourceProvider({
+ source,
+ grants,
+ host,
+ onNavigate,
+ children,
+}: ResourceProviderProps) {
+ const value = useMemo(
+ () => ({ source, grants, host, navigate: onNavigate ?? noNavigation }),
+ [source, grants, host, onNavigate]
+ )
+
+ return {children}
+}
+
+/**
+ * The axes of the resource this subtree is rendering, over every kind. Views
+ * that need a concrete {@link ResourceKind} use {@link useResourceOfKind};
+ * nothing here widens a share source into an addressable one.
+ */
+export function useResource(): ResourceContextValue {
+ const value = useContext(ResourceContext)
+ if (!value) {
+ throw new Error(
+ 'useResource must be rendered inside a . Mount the view with an explicit source, grants, and host.'
+ )
+ }
+ return value
+}
+
+/**
+ * The mounted resource, or `null` when there is none.
+ *
+ * For leaves that a resource view shares with surfaces that render no resource
+ * at all — the markdown image node view renders inside a file, and inside a
+ * standalone markdown field in a modal. Everything that only ever renders under
+ * a view uses {@link useResource} so a missing provider fails loudly.
+ */
+export function useOptionalResource(): ResourceContextValue | null {
+ return useContext(ResourceContext)
+}
+
+/**
+ * The mounted resource, narrowed to one kind.
+ *
+ * `ResourceSource`'s `kind` is not a discriminant across kinds, so nothing
+ * downstream can narrow on its own — this is the one place it happens. A
+ * renderer mounted against another kind fails loudly here rather than silently
+ * addressing the wrong routes.
+ */
+export function useResourceOfKind(kind: K): ResourceContextValue {
+ const value = useResource()
+ if (value.source.kind !== kind) {
+ throw new Error(`A ${kind} renderer was mounted against a ${value.source.kind} resource.`)
+ }
+ return value as ResourceContextValue
+}
+
+/**
+ * The mounted resource of one kind, or `null` when this subtree is not inside
+ * one — for leaves a view shares with surfaces that mount no resource at all.
+ */
+export function useOptionalResourceOfKind(
+ kind: K
+): ResourceContextValue | null {
+ const value = useOptionalResource()
+ if (!value || value.source.kind !== kind) return null
+ return value as ResourceContextValue
+}
diff --git a/apps/sim/components/resources/table-view/cell-formatting.test.ts b/apps/sim/components/resources/table-view/cell-formatting.test.ts
new file mode 100644
index 00000000000..7b30775bee7
--- /dev/null
+++ b/apps/sim/components/resources/table-view/cell-formatting.test.ts
@@ -0,0 +1,75 @@
+/**
+ * @vitest-environment node
+ *
+ * Every surface that draws a table resolves its cell text through the
+ * column-type registry, so a currency column reads `$1,234.50` and a select
+ * column shows its option *name* wherever it is mounted — the tables grid, an
+ * embedded panel, or a public share.
+ *
+ * This pins the registry contract, which is what stops a second surface from
+ * growing its own resolver. It regressed once exactly that way: the interface
+ * module carried a resolver handling only boolean/null/json/date/string and let
+ * currency and select fall through to `JSON.stringify`, so a module rendered
+ * `1234.5` and `opt_open` where the grid rendered `$1,234.50` and `Open`.
+ *
+ * Note the two halves reach the screen differently. Currency is the direct
+ * dependency — `resolveCellRender` calls `formatForDisplay` for it. Select is
+ * not: it resolves to the `select` kind and renders as pills, so these cases
+ * pin the id→name semantics `SelectPill` must agree with, not its render path.
+ */
+import { describe, expect, it } from 'vitest'
+import { columnTypeOf } from '@/lib/table/column-types'
+import type { ColumnDefinition } from '@/lib/table/types'
+
+function column(overrides: Partial & Pick) {
+ return { id: 'col_1', name: 'col', ...overrides } as ColumnDefinition
+}
+
+describe('table cell display formatting', () => {
+ it('formats currency through the registry, not as a bare number', () => {
+ const col = column({ type: 'currency', currencyCode: 'USD' })
+ const text = columnTypeOf(col).formatForDisplay(1234.5, col)
+
+ expect(text).not.toBe('1234.5')
+ expect(text).toContain('1,234.50')
+ })
+
+ it('resolves a select option id to its name', () => {
+ const col = column({
+ type: 'select',
+ options: [
+ { id: 'opt_open', name: 'Open' },
+ { id: 'opt_done', name: 'Done' },
+ ],
+ })
+
+ expect(columnTypeOf(col).formatForDisplay('opt_open', col)).toBe('Open')
+ })
+
+ it('joins a multi-select rather than emitting raw JSON', () => {
+ const col = column({
+ type: 'select',
+ multiple: true,
+ options: [
+ { id: 'opt_a', name: 'Alpha' },
+ { id: 'opt_b', name: 'Beta' },
+ ],
+ })
+ const text = columnTypeOf(col).formatForDisplay(['opt_a', 'opt_b'], col)
+
+ expect(text).not.toContain('opt_a')
+ expect(text).toBe('Alpha, Beta')
+ })
+
+ /**
+ * The registry's completeness gate means every column type has a formatter;
+ * that is what lets the cell layer use one fallback branch instead of a
+ * per-type switch that would drift from the grid's.
+ */
+ it('gives every column type a display formatter', () => {
+ for (const type of ['string', 'number', 'boolean', 'date', 'json', 'select', 'currency']) {
+ const col = column({ type: type as ColumnDefinition['type'] })
+ expect(typeof columnTypeOf(col).formatForDisplay, type).toBe('function')
+ }
+ })
+})
diff --git a/apps/sim/components/resources/table-view/cells/cell-content.tsx b/apps/sim/components/resources/table-view/cells/cell-content.tsx
new file mode 100644
index 00000000000..a512e1d440c
--- /dev/null
+++ b/apps/sim/components/resources/table-view/cells/cell-content.tsx
@@ -0,0 +1,82 @@
+'use client'
+
+import type { ReactNode } from 'react'
+import type { RowExecutionMetadata } from '@/lib/table'
+import type { DisplayColumn } from '../types'
+import { CellRender, resolveCellRender } from './cell-render'
+
+interface CellContentProps {
+ value: unknown
+ exec?: RowExecutionMetadata
+ column: DisplayColumn
+ /**
+ * Current workspace id — lets string cells holding an in-workspace resource URL
+ * render as a tagged-resource chip instead of a plain external link.
+ *
+ * Optional, and that is the security seam: the chip's renderer mounts
+ * workspace-authenticated list queries, so a surface with no workspace identity
+ * (an anonymous share) passes `undefined` and the resolver never emits that kind.
+ * See `cell-render.test.ts`.
+ */
+ workspaceId?: string
+ isEditing: boolean
+ /**
+ * The editing surface, supplied by the host that owns the write path. Injected
+ * rather than imported so a read-only surface never pulls the inline editor —
+ * `apps/sim` has no `sideEffects: false`, so a static import would ship it
+ * regardless of `isEditing`.
+ */
+ editor?: ReactNode
+ /**
+ * Human-readable labels for unmet deps on this row+group, used to render a
+ * "Waiting" pill when the cell hasn't run because something it depends on
+ * is empty. `undefined` (or empty) means no waiting state.
+ */
+ waitingOnLabels?: string[]
+ /** Column is an enrichment output — a completed-but-empty cell renders "Not found". */
+ isEnrichmentOutput?: boolean
+}
+
+/**
+ * Glue layer: maps cell inputs to a typed `CellRenderKind` (via the pure
+ * resolver) and renders the corresponding JSX (via the dumb renderer). The host's
+ * `editor` sits on top when `isEditing` is true. Adding a new cell appearance is a
+ * three-step mechanical change in the colocated files.
+ */
+export function CellContent({
+ value,
+ exec,
+ column,
+ workspaceId,
+ isEditing,
+ editor,
+ waitingOnLabels,
+ isEnrichmentOutput,
+}: CellContentProps) {
+ const kind = resolveCellRender({
+ value,
+ exec,
+ column,
+ waitingOnLabels,
+ isEnrichmentOutput,
+ currentWorkspaceId: workspaceId,
+ })
+
+ /**
+ * `isEditing` alone is not enough to dim the underlying cell. `CellRender`
+ * hides most kinds while editing because an editor is covering them — so a
+ * host that reports editing without supplying one would render a cell that is
+ * neither readable nor editable. Deriving both from the editor's presence
+ * makes that state unreachable rather than merely unused.
+ */
+ const showingEditor = isEditing && Boolean(editor)
+
+ return (
+ <>
+ {showingEditor && (
+ {editor}
+ )}
+
+ >
+ )
+}
diff --git a/apps/sim/components/resources/table-view/cells/cell-render.test.ts b/apps/sim/components/resources/table-view/cells/cell-render.test.ts
new file mode 100644
index 00000000000..73973bd6d1b
--- /dev/null
+++ b/apps/sim/components/resources/table-view/cells/cell-render.test.ts
@@ -0,0 +1,161 @@
+/**
+ * @vitest-environment node
+ *
+ * The security property of `resolveCellRender`: the `sim-resource` cell kind —
+ * the only kind whose renderer mounts workspace-authenticated queries — is
+ * unreachable without a `currentWorkspaceId`. A share-scope consumer passes
+ * `undefined` and gets a plain favicon link instead.
+ *
+ * `SimResourceCell` mounts `useWorkflows`, `useTablesList`, `useKnowledgeBasesQuery`
+ * and `useWorkspaceFiles`, so emitting this kind on a public surface would fire
+ * cookie-authenticated `/api/…` reads from an anonymous viewer. The guard lives in
+ * `resolveSimResourceKind`; these tests are what keep it there.
+ */
+import { describe, expect, it } from 'vitest'
+import type { DisplayColumn } from '@/components/resources/table-view'
+import { resolveCellRender } from '@/components/resources/table-view'
+import type { RowExecutionMetadata } from '@/lib/table'
+
+const WORKSPACE_ID = 'ws_00000000'
+
+function column(overrides: Partial = {}): DisplayColumn {
+ return {
+ id: 'col_link',
+ name: 'link',
+ type: 'string',
+ key: 'col_link',
+ groupSize: 1,
+ groupStartColIndex: 0,
+ headerLabel: 'link',
+ isGroupStart: true,
+ ...overrides,
+ } as DisplayColumn
+}
+
+/** A workflow-output column — the second code path that promotes a value to a link. */
+const workflowColumn = column({ workflowGroupId: 'grp_1', type: 'json', outputBlockId: 'blk_1' })
+
+const completedExec = { status: 'completed' } as RowExecutionMetadata
+
+/**
+ * Every URL shape that addresses a sim resource in the current workspace, in
+ * both the absolute and relative spellings the resolver accepts. Each entry is
+ * asserted to be a *real* `sim-resource` URL (with a workspace id) before being
+ * asserted not to produce that kind without one — so the negative assertions
+ * can never pass vacuously against a URL the resolver simply doesn't recognise.
+ */
+const IN_WORKSPACE_URLS = [
+ `https://sim.ai/workspace/${WORKSPACE_ID}/w/wf_1`,
+ `https://sim.ai/workspace/${WORKSPACE_ID}/tables/tbl_1`,
+ `https://sim.ai/workspace/${WORKSPACE_ID}/knowledge/kb_1`,
+ `https://sim.ai/workspace/${WORKSPACE_ID}/files/file_1`,
+ `/workspace/${WORKSPACE_ID}/w/wf_1`,
+ `/workspace/${WORKSPACE_ID}/tables/tbl_1`,
+ `/workspace/${WORKSPACE_ID}/knowledge/kb_1`,
+ `/workspace/${WORKSPACE_ID}/files/file_1`,
+ `/workspace/${WORKSPACE_ID}/files/file_1?download=1`,
+ `https://sim.ai/workspace/${WORKSPACE_ID}/w/wf_1/`,
+]
+
+/** Both call sites that can promote a cell value to a link. */
+const CELL_PATHS = [
+ { label: 'string column', column: column(), exec: undefined },
+ { label: 'workflow-output column', column: workflowColumn, exec: completedExec },
+] as const
+
+describe('resolveCellRender — sim-resource requires a workspace id', () => {
+ it.each(IN_WORKSPACE_URLS)('emits sim-resource for %s when the workspace id matches', (url) => {
+ for (const path of CELL_PATHS) {
+ const kind = resolveCellRender({
+ value: url,
+ exec: path.exec,
+ column: path.column,
+ waitingOnLabels: undefined,
+ currentWorkspaceId: WORKSPACE_ID,
+ })
+ expect(kind.kind, `${path.label}: ${url}`).toBe('sim-resource')
+ }
+ })
+
+ it.each(IN_WORKSPACE_URLS)('never emits sim-resource for %s without a workspace id', (url) => {
+ for (const path of CELL_PATHS) {
+ const kind = resolveCellRender({
+ value: url,
+ exec: path.exec,
+ column: path.column,
+ waitingOnLabels: undefined,
+ currentWorkspaceId: undefined,
+ })
+ expect(kind.kind, `${path.label}: ${url}`).not.toBe('sim-resource')
+ }
+ })
+
+ it('falls through to a plain external link, not a resource chip', () => {
+ const kind = resolveCellRender({
+ value: `https://sim.ai/workspace/${WORKSPACE_ID}/tables/tbl_1`,
+ exec: undefined,
+ column: column(),
+ waitingOnLabels: undefined,
+ currentWorkspaceId: undefined,
+ })
+ expect(kind).toEqual({
+ kind: 'url',
+ text: `https://sim.ai/workspace/${WORKSPACE_ID}/tables/tbl_1`,
+ href: `https://sim.ai/workspace/${WORKSPACE_ID}/tables/tbl_1`,
+ domain: 'sim.ai',
+ })
+ })
+
+ it('does not emit sim-resource for a URL in a different workspace', () => {
+ const kind = resolveCellRender({
+ value: '/workspace/ws_other/tables/tbl_1',
+ exec: undefined,
+ column: column(),
+ waitingOnLabels: undefined,
+ currentWorkspaceId: WORKSPACE_ID,
+ })
+ expect(kind.kind).not.toBe('sim-resource')
+ })
+
+ it('emits no sim-resource kind for any cell shape when the workspace id is absent', () => {
+ const values: unknown[] = [
+ ...IN_WORKSPACE_URLS,
+ null,
+ undefined,
+ '',
+ 'plain text',
+ 'example.com',
+ 'https://example.com/path',
+ 42,
+ true,
+ { href: `/workspace/${WORKSPACE_ID}/w/wf_1` },
+ [`/workspace/${WORKSPACE_ID}/w/wf_1`],
+ ]
+ const columns: DisplayColumn[] = [
+ column({ type: 'string' }),
+ column({ type: 'number' }),
+ column({ type: 'boolean' }),
+ column({ type: 'date' }),
+ column({ type: 'json' }),
+ column({ type: 'currency', currencyCode: 'USD' }),
+ column({ type: 'select', options: [{ id: 'opt_a', name: 'A' }] }),
+ workflowColumn,
+ ]
+ const execs: Array = [undefined, completedExec]
+
+ for (const value of values) {
+ for (const col of columns) {
+ for (const exec of execs) {
+ const kind = resolveCellRender({
+ value,
+ exec,
+ column: col,
+ waitingOnLabels: undefined,
+ currentWorkspaceId: undefined,
+ })
+ expect(kind.kind, `${col.type} / ${String(value)}`).not.toBe('sim-resource')
+ }
+ }
+ }
+ })
+})
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/cell-render.tsx b/apps/sim/components/resources/table-view/cells/cell-render.tsx
similarity index 98%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/cell-render.tsx
rename to apps/sim/components/resources/table-view/cells/cell-render.tsx
index 4e16d03912b..27d737502c5 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/cell-render.tsx
+++ b/apps/sim/components/resources/table-view/cells/cell-render.tsx
@@ -4,13 +4,13 @@ import type React from 'react'
import { useEffect, useRef, useState } from 'react'
import { Badge, Checkbox, cn, Tooltip } from '@sim/emcn'
import { parse } from 'tldts'
+import { StatusBadge } from '@/components/execution-status'
import { faviconUrl } from '@/lib/core/utils/favicon'
import type { RowExecutionMetadata, SelectOption } from '@/lib/table'
import { columnTypeOf } from '@/lib/table/column-types'
-import { StatusBadge } from '@/app/workspace/[workspaceId]/logs/utils'
-import { storageToDisplay } from '../../../utils'
-import { resolveSelectOptions, SelectPill } from '../../select-field'
+import { resolveSelectOptions, SelectPill } from '../select-pill'
import type { DisplayColumn } from '../types'
+import { storageToDisplay } from '../values'
import { SimResourceCell, type SimResourceType } from './sim-resource-cell'
export type CellRenderKind =
diff --git a/apps/sim/components/resources/table-view/cells/index.ts b/apps/sim/components/resources/table-view/cells/index.ts
new file mode 100644
index 00000000000..e183e0bb175
--- /dev/null
+++ b/apps/sim/components/resources/table-view/cells/index.ts
@@ -0,0 +1,3 @@
+export { CellContent } from './cell-content'
+export { CellRender, type CellRenderKind, resolveCellRender } from './cell-render'
+export { SimResourceCell, type SimResourceType } from './sim-resource-cell'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/sim-resource-cell.tsx b/apps/sim/components/resources/table-view/cells/sim-resource-cell.tsx
similarity index 94%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/sim-resource-cell.tsx
rename to apps/sim/components/resources/table-view/cells/sim-resource-cell.tsx
index fdbd2776e97..f146ee1ada9 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/sim-resource-cell.tsx
+++ b/apps/sim/components/resources/table-view/cells/sim-resource-cell.tsx
@@ -2,8 +2,8 @@
import { useMemo } from 'react'
import { cn } from '@sim/emcn'
-import { ContextMentionIcon } from '@/app/workspace/[workspaceId]/home/components/context-mention-icon'
-import type { ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types'
+import { ContextMentionIcon } from '@/components/chat/context-mention-icon'
+import type { ChatMessageContext } from '@/components/chat/types'
import { useKnowledgeBasesQuery } from '@/hooks/queries/kb/knowledge'
import { useTablesList } from '@/hooks/queries/tables'
import { useWorkflows } from '@/hooks/queries/workflows'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/constants.ts b/apps/sim/components/resources/table-view/constants.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/constants.ts
rename to apps/sim/components/resources/table-view/constants.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/data-row.tsx b/apps/sim/components/resources/table-view/data-row.tsx
similarity index 91%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/data-row.tsx
rename to apps/sim/components/resources/table-view/data-row.tsx
index b73bf68dc49..887b93ea108 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/data-row.tsx
+++ b/apps/sim/components/resources/table-view/data-row.tsx
@@ -1,12 +1,11 @@
'use client'
-import React from 'react'
+import React, { type ReactNode } from 'react'
import { Button, Checkbox, cn, handleKeyboardActivation } from '@sim/emcn'
import { PlayOutline, Square } from '@sim/emcn/icons'
import type { ActiveDispatch } from '@/lib/api/contracts/tables'
import type { TableRow as TableRowType, WorkflowGroup } from '@/lib/table'
import { getUnmetGroupDeps } from '@/lib/table/deps'
-import type { SaveReason } from '../../types'
import { CellContent } from './cells'
import {
CELL,
@@ -21,19 +20,24 @@ import { type NormalizedSelection, resolveCellExec } from './utils'
export interface DataRowProps {
row: TableRowType
columns: DisplayColumn[]
- /** Current workspace id — forwarded to cells so in-workspace resource URLs
- * render as tagged-resource chips. */
- workspaceId: string
+ /**
+ * Current workspace id — forwarded to cells so in-workspace resource URLs render
+ * as tagged-resource chips. Optional: a surface with no workspace identity (an
+ * anonymous share) omits it and those chips are never emitted.
+ */
+ workspaceId?: string
+ /**
+ * Builds the inline editing surface for a cell. Supplied by the host that owns
+ * the write path, so a read-only surface renders — and bundles — no editor.
+ */
+ renderCellEditor?: (cell: { row: TableRowType; column: DisplayColumn }) => ReactNode
rowIndex: number
isFirstRow: boolean
editingColumnName: string | null
- initialCharacter: string | null
pendingCellValue: Record | null
normalizedSelection: NormalizedSelection | null
onClick: (rowId: string, columnName: string, options?: { toggleBoolean?: boolean }) => void
onDoubleClick: (rowId: string, columnName: string, columnKey: string) => void
- onSave: (rowId: string, columnName: string, value: unknown, reason: SaveReason) => void
- onCancel: () => void
onContextMenu: (e: React.MouseEvent, row: TableRowType) => void
onCellMouseDown: (rowIndex: number, colIndex: number, shiftKey: boolean) => void
onCellMouseEnter: (rowIndex: number, colIndex: number) => void
@@ -111,8 +115,6 @@ function dataRowPropsAreEqual(prev: DataRowProps, next: DataRowProps): boolean {
prev.pendingCellValue !== next.pendingCellValue ||
prev.onClick !== next.onClick ||
prev.onDoubleClick !== next.onDoubleClick ||
- prev.onSave !== next.onSave ||
- prev.onCancel !== next.onCancel ||
prev.onContextMenu !== next.onContextMenu ||
prev.onCellMouseDown !== next.onCellMouseDown ||
prev.onCellMouseEnter !== next.onCellMouseEnter ||
@@ -132,9 +134,21 @@ function dataRowPropsAreEqual(prev: DataRowProps, next: DataRowProps): boolean {
) {
return false
}
+
+ /**
+ * `renderCellEditor` is only ever read under `isEditing`, and `isEditing`
+ * requires this row's `editingColumnName` — so a row that is not editing does
+ * not care that the callback's identity changed.
+ *
+ * The gate is load-bearing, not a micro-optimisation: the callback closes over
+ * the grid's pending-update and initial-character state, so it is rebuilt on
+ * every keystroke that opens an editor and on every in-flight save. Comparing
+ * it unconditionally would re-render every mounted row on each of those,
+ * where exactly one row needs to.
+ */
if (
(prev.editingColumnName !== null || next.editingColumnName !== null) &&
- prev.initialCharacter !== next.initialCharacter
+ prev.renderCellEditor !== next.renderCellEditor
) {
return false
}
@@ -154,14 +168,12 @@ export const DataRow = React.memo(function DataRow({
rowIndex,
isFirstRow,
editingColumnName,
- initialCharacter,
pendingCellValue,
+ renderCellEditor,
normalizedSelection,
isRowChecked,
onClick,
onDoubleClick,
- onSave,
- onCancel,
onContextMenu,
onCellMouseDown,
onCellMouseEnter,
@@ -376,9 +388,7 @@ export const DataRow = React.memo(function DataRow({
)}
column={column}
isEditing={isEditing}
- initialCharacter={isEditing ? initialCharacter : undefined}
- onSave={(value, reason) => onSave(row.id, column.key, value, reason)}
- onCancel={onCancel}
+ editor={isEditing ? renderCellEditor?.({ row, column }) : undefined}
waitingOnLabels={
column.workflowGroupId
? (waitingByGroupId?.get(column.workflowGroupId) ?? undefined)
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-header-menu.tsx b/apps/sim/components/resources/table-view/headers/column-header-menu.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-header-menu.tsx
rename to apps/sim/components/resources/table-view/headers/column-header-menu.tsx
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-type-icon.tsx b/apps/sim/components/resources/table-view/headers/column-type-icon.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-type-icon.tsx
rename to apps/sim/components/resources/table-view/headers/column-type-icon.tsx
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/index.ts b/apps/sim/components/resources/table-view/headers/index.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/index.ts
rename to apps/sim/components/resources/table-view/headers/index.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/workflow-group-meta-cell.tsx b/apps/sim/components/resources/table-view/headers/workflow-group-meta-cell.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/workflow-group-meta-cell.tsx
rename to apps/sim/components/resources/table-view/headers/workflow-group-meta-cell.tsx
diff --git a/apps/sim/components/resources/table-view/index.ts b/apps/sim/components/resources/table-view/index.ts
new file mode 100644
index 00000000000..22cfe9dafb9
--- /dev/null
+++ b/apps/sim/components/resources/table-view/index.ts
@@ -0,0 +1,97 @@
+/**
+ * The table resource's view layer — everything that draws a table and nothing
+ * that writes one.
+ *
+ * Moved out of `app/workspace/[workspaceId]/tables/[tableId]/` so it stops being
+ * addressable only from inside the workspace route tree. The editing shell
+ * (`TableGrid` and the mutation surfaces it owns) stays behind and mounts these;
+ * the dependency runs shell → unit and never back.
+ *
+ * The split line is the write path. Nothing exported here mounts a mutation, reads
+ * a permission context, or calls `useParams()`; the two props that would carry
+ * workspace identity — `CellContent.workspaceId` and `DataRow.workspaceId` — are
+ * optional precisely so a surface without one can render. See
+ * `cells/cell-render.test.ts` for the property that makes that safe.
+ *
+ * This is the unit barrel: import from `@/components/resources/table-view`, not
+ * from a file inside it. The exception is a `lazy()`/`dynamic()` split point,
+ * which must use a deep path — `apps/sim` has no `sideEffects: false`, so routing
+ * a split point through a barrel silently re-attaches the chunk.
+ */
+
+export { CellContent, CellRender, type CellRenderKind, resolveCellRender } from './cells'
+export {
+ ADD_COL_WIDTH,
+ CELL,
+ CELL_CHECKBOX,
+ CELL_CONTENT,
+ CELL_HEADER_CHECKBOX,
+ COL_WIDTH,
+ COLUMN_SIDEBAR_WIDTH,
+ SELECTION_OVERLAY,
+ SELECTION_TINT_BG,
+} from './constants'
+export { DataRow, type DataRowProps } from './data-row'
+export {
+ ColumnHeaderMenu,
+ ColumnOptionsMenu,
+ ColumnTypeIcon,
+ columnTypeIcon,
+ WorkflowGroupMetaCell,
+} from './headers'
+export { RemoteSelectionOverlay } from './remote-selection-overlay'
+export {
+ resolveSelectOptions,
+ SelectPill,
+ selectedOptionIds,
+ toSelectedIds,
+} from './select-pill'
+export { TableFind, type TableFindProps } from './table-find'
+export { AddRowButton, SelectAllCheckbox, TableColGroup } from './table-primitives'
+export type {
+ BlockIconInfo,
+ ColumnSourceInfo,
+ DisplayColumn,
+ EditingCell,
+ RemoteTableSelection,
+ SaveReason,
+} from './types'
+export {
+ buildHeaderGroups,
+ buildTableSelectionContext,
+ type CellCoord,
+ canWriteRowsWithChip,
+ checkboxColLayout,
+ chipRowCount,
+ classifyExecStatusMix,
+ collectRowSnapshots,
+ computeNormalizedSelection,
+ drainTargetForChip,
+ type ExecStatusMix,
+ expandToDisplayColumns,
+ type HeaderGroup,
+ isCellInSelection,
+ moveCell,
+ type NormalizedSelection,
+ ROW_SELECTION_ALL,
+ ROW_SELECTION_NONE,
+ type RowSelection,
+ readExecution,
+ resolveCellExec,
+ rowSelectionCoversAll,
+ rowSelectionIncludes,
+ rowSelectionIsEmpty,
+ rowSelectionMaterialize,
+ selectedColumnIds,
+} from './utils'
+export {
+ cleanCellValue,
+ type DateCellLocalParts,
+ dateValueToLocalParts,
+ displayToStorage,
+ formatValueForInput,
+ generateColumnName,
+ localPartsToDateValue,
+ storageToDisplay,
+ todayLocalCalendarDate,
+} from './values'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/remote-selection-overlay.tsx b/apps/sim/components/resources/table-view/remote-selection-overlay.tsx
similarity index 98%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/remote-selection-overlay.tsx
rename to apps/sim/components/resources/table-view/remote-selection-overlay.tsx
index 5461082f3de..b60b3e7c2ea 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/remote-selection-overlay.tsx
+++ b/apps/sim/components/resources/table-view/remote-selection-overlay.tsx
@@ -3,11 +3,8 @@
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import { getUserColor, withAlpha } from '@/lib/workspaces/colors'
-import {
- isCellInSelection,
- type NormalizedSelection,
-} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils'
-import type { RemoteTableSelection } from '@/app/workspace/[workspaceId]/tables/[tableId]/hooks/use-table-room'
+import type { RemoteTableSelection } from './types'
+import { isCellInSelection, type NormalizedSelection } from './utils'
/** A measured remote selection, positioned in the grid content wrapper's space. */
interface SelectionBox {
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/select-field/select-pill.tsx b/apps/sim/components/resources/table-view/select-pill.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/select-field/select-pill.tsx
rename to apps/sim/components/resources/table-view/select-pill.tsx
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-find.tsx b/apps/sim/components/resources/table-view/table-find.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-find.tsx
rename to apps/sim/components/resources/table-view/table-find.tsx
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-primitives.tsx b/apps/sim/components/resources/table-view/table-primitives.tsx
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-primitives.tsx
rename to apps/sim/components/resources/table-view/table-primitives.tsx
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/types.ts b/apps/sim/components/resources/table-view/types.ts
similarity index 55%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/types.ts
rename to apps/sim/components/resources/table-view/types.ts
index af5cceea88c..501037f71e1 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/types.ts
+++ b/apps/sim/components/resources/table-view/types.ts
@@ -1,4 +1,5 @@
import type React from 'react'
+import type { TableCellSelection } from '@sim/realtime-protocol/table-presence'
import type { ColumnDefinition } from '@/lib/table'
export interface BlockIconInfo {
@@ -35,3 +36,35 @@ export interface DisplayColumn extends ColumnDefinition {
/** True when this is the leftmost sibling of its group (or non-grouped). */
isGroupStart: boolean
}
+
+/**
+ * A remote viewer's current cell selection, ready to render as a presence overlay.
+ *
+ * Declared beside the grid's own view types rather than in the presence hook: the
+ * overlay that draws it is presentational, while the hook that produces it holds an
+ * authenticated socket session. Keeping the type here lets the overlay stay free of
+ * any dependency on the hook.
+ */
+export interface RemoteTableSelection {
+ socketId: string
+ userId: string
+ userName: string
+ cell: NonNullable
+}
+
+/**
+ * Reason the inline editor completed, used to determine navigation after save
+ */
+export type SaveReason = 'enter' | 'tab' | 'shift-tab' | 'blur'
+
+/**
+ * Tracks which cell is currently being edited inline. `columnKey` distinguishes
+ * fanned-out workflow visual columns (which share the same `columnName`) — set
+ * when the interaction targets a specific visual column (e.g. expanded view),
+ * omitted for plain cells.
+ */
+export interface EditingCell {
+ rowId: string
+ columnName: string
+ columnKey?: string
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.test.ts b/apps/sim/components/resources/table-view/utils.test.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.test.ts
rename to apps/sim/components/resources/table-view/utils.test.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.ts b/apps/sim/components/resources/table-view/utils.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.ts
rename to apps/sim/components/resources/table-view/utils.ts
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/utils.test.ts b/apps/sim/components/resources/table-view/values.test.ts
similarity index 99%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/utils.test.ts
rename to apps/sim/components/resources/table-view/values.test.ts
index 5945be6c388..c858116be87 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/utils.test.ts
+++ b/apps/sim/components/resources/table-view/values.test.ts
@@ -9,7 +9,7 @@ import {
formatValueForInput,
localPartsToDateValue,
storageToDisplay,
-} from '@/app/workspace/[workspaceId]/tables/[tableId]/utils'
+} from '@/components/resources/table-view'
describe('dateValueToLocalParts / localPartsToDateValue', () => {
it('splits calendar dates without a time part and round-trips', () => {
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/utils.ts b/apps/sim/components/resources/table-view/values.ts
similarity index 100%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/utils.ts
rename to apps/sim/components/resources/table-view/values.ts
diff --git a/apps/sim/components/ui/generated-password-input.test.tsx b/apps/sim/components/ui/chip-password-input.test.tsx
similarity index 79%
rename from apps/sim/components/ui/generated-password-input.test.tsx
rename to apps/sim/components/ui/chip-password-input.test.tsx
index e50ad2d4823..6a2c0d18c4a 100644
--- a/apps/sim/components/ui/generated-password-input.test.tsx
+++ b/apps/sim/components/ui/chip-password-input.test.tsx
@@ -1,45 +1,16 @@
/**
* @vitest-environment jsdom
+ *
+ * Behavioural coverage for the saved-password disclosure flow, carried over
+ * verbatim when `GeneratedPasswordInput` was retired in favour of the canonical
+ * {@link ChipPasswordInput}. The component moved packages; the guarantees did
+ * not, so these assertions still address it the way a user does — by aria-label
+ * and by what the field actually renders.
*/
-import { act, type ButtonHTMLAttributes, type InputHTMLAttributes, type ReactNode } from 'react'
+import { act } from 'react'
+import { ChipPasswordInput } from '@sim/emcn'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { GeneratedPasswordInput } from '@/components/ui/generated-password-input'
-
-const { mockCopy } = vi.hoisted(() => ({
- mockCopy: vi.fn(async () => true),
-}))
-
-vi.mock('@sim/emcn', () => ({
- Button: ({
- children,
- variant: _variant,
- ...props
- }: {
- children?: ReactNode
- variant?: string
- } & ButtonHTMLAttributes) => {children} ,
- ChipInput: ({
- endAdornment,
- error: _error,
- ...props
- }: {
- endAdornment?: ReactNode
- error?: boolean
- } & InputHTMLAttributes) => (
-
-
- {endAdornment}
-
- ),
- Loader: () => ,
- Tooltip: {
- Root: ({ children }: { children?: ReactNode }) => children,
- Trigger: ({ children }: { children?: ReactNode }) => children,
- Content: () => null,
- },
- useCopyToClipboard: () => ({ copied: false, copy: mockCopy }),
-}))
let container: HTMLDivElement
let root: Root
@@ -47,22 +18,23 @@ let root: Root
interface RenderInputOptions {
fetchCurrentPassword?: () => Promise
onChange?: (value: string) => void
- showGenerate?: boolean
+ onGenerate?: boolean
value?: string
}
function renderInput({
fetchCurrentPassword,
onChange = vi.fn(),
- showGenerate = false,
+ onGenerate = false,
value = '',
}: RenderInputOptions = {}) {
act(() => {
root.render(
- 'g'.repeat(24) : undefined}
fetchCurrentPassword={fetchCurrentPassword}
/>
)
@@ -81,7 +53,7 @@ function passwordButton(label: string): HTMLButtonElement {
return button
}
-describe('GeneratedPasswordInput', () => {
+describe('ChipPasswordInput', () => {
beforeEach(() => {
;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
container = document.createElement('div')
@@ -169,7 +141,7 @@ describe('GeneratedPasswordInput', () => {
it('keeps a generated password hidden when the field is hidden', () => {
const fetchCurrentPassword = vi.fn().mockResolvedValue('saved-secret')
const onChange = vi.fn()
- renderInput({ fetchCurrentPassword, onChange, showGenerate: true })
+ renderInput({ fetchCurrentPassword, onChange, onGenerate: true })
act(() => passwordButton('Generate password').click())
@@ -181,7 +153,7 @@ describe('GeneratedPasswordInput', () => {
it('keeps a generated password visible when the field is visible', async () => {
const fetchCurrentPassword = vi.fn().mockResolvedValue('saved-secret')
const onChange = vi.fn()
- renderInput({ fetchCurrentPassword, onChange, showGenerate: true })
+ renderInput({ fetchCurrentPassword, onChange, onGenerate: true })
await act(async () => passwordButton('Show password').click())
act(() => passwordButton('Generate password').click())
diff --git a/apps/sim/components/ui/generated-password-input.tsx b/apps/sim/components/ui/generated-password-input.tsx
deleted file mode 100644
index e1d09f880a2..00000000000
--- a/apps/sim/components/ui/generated-password-input.tsx
+++ /dev/null
@@ -1,163 +0,0 @@
-'use client'
-
-import { useState } from 'react'
-import { Button, ChipInput, Loader, Tooltip, useCopyToClipboard } from '@sim/emcn'
-import { Check, Clipboard, Eye, EyeOff, RefreshCw } from '@sim/emcn/icons'
-import { generatePassword } from '@/lib/core/security/encryption'
-
-const MASKED_PASSWORD = '••••••••'
-
-interface GeneratedPasswordInputProps {
- value: string
- onChange: (value: string) => void
- disabled?: boolean
- placeholder?: string
- /** Show the Generate (random password) action. Off for consumer-facing entry forms. */
- showGenerate?: boolean
- required?: boolean
- autoComplete?: string
- error?: boolean
- /**
- * Resolves the currently saved password when the Show toggle is clicked.
- * While hidden, an empty field displays a masked placeholder.
- */
- fetchCurrentPassword?: () => Promise
-}
-
-/**
- * Password field with reveal / copy / (optional) generate adornments, used by the
- * deploy-as-chat access controls and the file-share modal. Owns its show/copy UI
- * state; the caller owns the value.
- */
-export function GeneratedPasswordInput({
- value,
- onChange,
- disabled = false,
- placeholder,
- showGenerate = true,
- required = false,
- autoComplete = 'new-password',
- error = false,
- fetchCurrentPassword,
-}: GeneratedPasswordInputProps) {
- const [showPassword, setShowPassword] = useState(false)
- const [currentPassword, setCurrentPassword] = useState(null)
- const [isFetchingCurrent, setIsFetchingCurrent] = useState(false)
- const { copied, copy } = useCopyToClipboard()
-
- const displayValue = currentPassword ?? value
- const displayPlaceholder = fetchCurrentPassword && !displayValue ? MASKED_PASSWORD : placeholder
-
- const handleChange = (nextValue: string) => {
- setCurrentPassword(null)
- onChange(nextValue)
- }
-
- const handleGeneratePassword = () => {
- handleChange(generatePassword(24))
- }
-
- const toggleShowPassword = async () => {
- if (showPassword) {
- setShowPassword(false)
- /**
- * Discard the fetched password instead of masking it. Keeping it would
- * leave the plaintext in the input's DOM value and keep Copy armed while
- * the field reads as hidden. A later reveal re-fetches, which also keeps
- * the audit log at one entry per disclosure. An edited value lives in
- * `value` and is deliberately untouched.
- */
- setCurrentPassword(null)
- return
- }
-
- if (!displayValue && fetchCurrentPassword) {
- setIsFetchingCurrent(true)
- try {
- setCurrentPassword(await fetchCurrentPassword())
- } catch {
- return
- } finally {
- setIsFetchingCurrent(false)
- }
- }
-
- setShowPassword(true)
- }
-
- return (
- handleChange(e.target.value)}
- disabled={disabled}
- required={required}
- autoComplete={autoComplete}
- error={error}
- endAdornment={
-
- {showGenerate ? (
-
-
-
-
-
-
-
- Generate
-
-
- ) : null}
-
-
- copy(displayValue)}
- disabled={!displayValue || disabled}
- aria-label='Copy password'
- className='!p-1.5'
- >
- {copied ? : }
-
-
-
- {copied ? 'Copied' : 'Copy'}
-
-
-
-
-
- {isFetchingCurrent ? (
-
- ) : showPassword ? (
-
- ) : (
-
- )}
-
-
-
- {showPassword ? 'Hide' : 'Show'}
-
-
-
- }
- />
- )
-}
diff --git a/apps/sim/components/ui/index.ts b/apps/sim/components/ui/index.ts
index 234f6f50a60..38c0867decf 100644
--- a/apps/sim/components/ui/index.ts
+++ b/apps/sim/components/ui/index.ts
@@ -1,5 +1,4 @@
export { Button, buttonVariants } from './button'
-export { GeneratedPasswordInput } from './generated-password-input'
export { Progress } from './progress'
export {
Select,
diff --git a/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts b/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts
index 4cf18a9f3a2..c45172d3fdf 100644
--- a/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts
+++ b/apps/sim/executor/handlers/pi/cloud-review-tools.test.ts
@@ -2,7 +2,7 @@
* @vitest-environment node
*/
import { execFile } from 'node:child_process'
-import { mkdir, mkdtemp, rm, symlink, writeFile as writeLocalFile } from 'node:fs/promises'
+import { mkdir, mkdtemp, rm, writeFile as writeLocalFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { promisify } from 'node:util'
@@ -61,70 +61,6 @@ describe('cloud review tools', () => {
expect(source).not.toContain('--unified=20')
})
- it('enforces read-size and canonical path bounds in the actual helper', async () => {
- await installCloudReviewTools(runner)
- const source = writeFile.mock.calls[0][1] as string
- const testDir = await mkdtemp(join(tmpdir(), 'sim-review-tools-'))
- const repoDir = join(testDir, 'repo')
- const scriptPath = join(testDir, 'review-tools.py')
- const outsidePath = join(testDir, 'outside.txt')
-
- try {
- await mkdir(repoDir)
- await writeLocalFile(
- scriptPath,
- source.replace(
- "pathlib.Path('/workspace/repo')",
- `pathlib.Path(${JSON.stringify(repoDir)})`
- )
- )
- await writeLocalFile(join(repoDir, 'safe.txt'), 'one\ntwo\n')
- await writeLocalFile(outsidePath, 'secret')
- await symlink(outsidePath, join(repoDir, 'escape.txt'))
- await mkdir(join(repoDir, '.git'))
- await writeLocalFile(join(repoDir, '.git', 'secret.txt'), 'DO_NOT_EXPOSE')
-
- const execute = (operation: string, args: Record) =>
- execFileAsync('python3', [scriptPath], {
- env: {
- ...process.env,
- REVIEW_TOOL_OPERATION: operation,
- REVIEW_TOOL_ARGS: JSON.stringify(args),
- },
- })
-
- await expect(
- execute('read', { path: 'safe.txt', offset: 1, limit: 2 })
- ).resolves.toMatchObject({
- stdout: '1: one\n2: two',
- })
- await expect(execute('read', { path: '../outside.txt' })).rejects.toMatchObject({
- stderr: expect.stringContaining('path must stay within the repository'),
- })
- await expect(execute('read', { path: 'escape.txt' })).rejects.toMatchObject({
- stderr: expect.stringContaining('path resolves outside the repository'),
- })
-
- const found = await execute('find', { path: '.', pattern: '**/*', limit: 20 })
- expect(found.stdout).toContain('safe.txt')
- expect(found.stdout).not.toContain('.git')
- const searched = await execute('search', {
- path: '.',
- pattern: 'DO_NOT_EXPOSE',
- glob: '**/*',
- literal: true,
- })
- expect(searched.stdout).toBe('No matches found')
-
- await writeLocalFile(join(repoDir, 'large.bin'), Buffer.alloc(5_000_001))
- await expect(execute('read', { path: 'large.bin' })).rejects.toMatchObject({
- stderr: expect.stringContaining('exceeds the 5 MB read limit'),
- })
- } finally {
- await rm(testDir, { recursive: true, force: true })
- }
- })
-
it('validates inline coordinates against an exact local diff', async () => {
await installCloudReviewTools(runner)
const source = writeFile.mock.calls[0][1] as string
diff --git a/apps/sim/executor/utils/start-block.test.ts b/apps/sim/executor/utils/start-block.test.ts
index 98b5c80d15d..2a311ae44d3 100644
--- a/apps/sim/executor/utils/start-block.test.ts
+++ b/apps/sim/executor/utils/start-block.test.ts
@@ -119,6 +119,41 @@ describe('start-block utilities', () => {
expect(output.files).toEqual(files)
})
+ it.concurrent(
+ 'resolves the unified start block for form submissions and coerces values per inputFormat',
+ () => {
+ const startBlock = createBlock('start_trigger', 'start', {
+ subBlocks: {
+ inputFormat: {
+ value: [
+ { name: 'quantity', type: 'number' },
+ { name: 'subscribed', type: 'boolean' },
+ { name: 'notes', type: 'string' },
+ ],
+ },
+ },
+ })
+
+ const resolution = resolveExecutorStartBlock([startBlock], {
+ execution: 'api',
+ isChildWorkflow: false,
+ })
+
+ expect(resolution?.blockId).toBe('start')
+ expect(resolution?.path).toBe(StartBlockPath.UNIFIED)
+ if (!resolution) return
+
+ const output = buildStartBlockOutput({
+ resolution,
+ workflowInput: { quantity: '5', subscribed: 'true', notes: 'hello' },
+ })
+
+ expect(output.quantity).toBe(5)
+ expect(output.subscribed).toBe(true)
+ expect(output.notes).toBe('hello')
+ }
+ )
+
it.concurrent('buildStartBlockOutput normalizes Start files from internal serve URLs', () => {
const block = createBlock('start_trigger', 'start')
const resolution = {
@@ -490,6 +525,93 @@ describe('start-block utilities', () => {
)
})
+ describe('form trigger submissions', () => {
+ it.concurrent('lands every submitted field as a top-level Start output', () => {
+ const block = createBlock('start_trigger', 'start')
+ const resolution = {
+ blockId: 'start',
+ block,
+ path: StartBlockPath.UNIFIED,
+ } as const
+
+ const output = buildStartBlockOutput({
+ resolution,
+ workflowInput: { email: 'ada@sim.ai', message: 'hello', subscribed: false },
+ })
+
+ expect(output.email).toBe('ada@sim.ai')
+ expect(output.message).toBe('hello')
+ expect(output.subscribed).toBe(false)
+ expect(output.input).toBeUndefined()
+ expect(output).not.toHaveProperty('conversationId')
+ })
+
+ it.concurrent('passes undeclared fields through alongside inputFormat-coerced ones', () => {
+ const block = createBlock('start_trigger', 'start', {
+ subBlocks: {
+ inputFormat: {
+ value: [{ name: 'quantity', type: 'number' }],
+ },
+ },
+ })
+ const resolution = {
+ blockId: 'start',
+ block,
+ path: StartBlockPath.UNIFIED,
+ } as const
+
+ const output = buildStartBlockOutput({
+ resolution,
+ workflowInput: { quantity: '7', notes: 'ship fast', subscribed: false },
+ })
+
+ expect(output.quantity).toBe(7)
+ expect(output.notes).toBe('ship fast')
+ expect(output.subscribed).toBe(false)
+ })
+
+ it.concurrent('keeps a submitted false switch value over the inputFormat default', () => {
+ const block = createBlock('start_trigger', 'start', {
+ subBlocks: {
+ inputFormat: {
+ value: [{ name: 'subscribed', type: 'boolean', value: true }],
+ },
+ },
+ })
+ const resolution = {
+ blockId: 'start',
+ block,
+ path: StartBlockPath.UNIFIED,
+ } as const
+
+ const output = buildStartBlockOutput({
+ resolution,
+ workflowInput: { subscribed: false },
+ })
+
+ expect(output.subscribed).toBe(false)
+ })
+
+ it.concurrent('enters a legacy API-trigger workflow at its API trigger', () => {
+ const resolution = resolveExecutorStartBlock([createBlock('api_trigger', 'api')], {
+ execution: 'api',
+ isChildWorkflow: false,
+ })
+
+ expect(resolution?.blockId).toBe('api')
+ expect(resolution?.path).toBe(StartBlockPath.SPLIT_API)
+ })
+
+ it.concurrent('resolves no start block for a chat-only workflow', () => {
+ const resolution = resolveExecutorStartBlock([createBlock('chat_trigger', 'chat')], {
+ execution: 'api',
+ isChildWorkflow: false,
+ })
+
+ expect(resolution).toBeNull()
+ })
+ })
+
describe('EXTERNAL_TRIGGER path', () => {
it.concurrent('rejects reserved runtime input keys copied to external trigger output', () => {
const block = createBlock('webhook', 'start')
diff --git a/apps/sim/hooks/queries/public-shares.ts b/apps/sim/hooks/queries/public-shares.ts
index 8793405055d..d8eae2a5c4d 100644
--- a/apps/sim/hooks/queries/public-shares.ts
+++ b/apps/sim/hooks/queries/public-shares.ts
@@ -7,6 +7,7 @@ import {
getFileShareContract,
requestPublicFileOtpContract,
type ShareRecord,
+ type ShareResourceType,
type UpsertFileShareBody,
upsertFileShareContract,
type VerifyPublicFileOtpResponse,
@@ -14,16 +15,23 @@ import {
} from '@/lib/api/contracts/public-shares'
import { workspaceFilesKeys } from '@/hooks/queries/workspace-files'
-export const FILE_SHARE_STALE_TIME = 30 * 1000
+export const RESOURCE_SHARE_STALE_TIME = 30 * 1000
+
+/** The resource families the share modal can publish. Folders ride the file page and have no share UI. */
+export type ShareableResourceType = Extract
/**
- * Query key factories for public shares
+ * Query key factories for public shares.
+ *
+ * One namespace covers every shared resource family: `scopeId` is the workspace
+ * the resource belongs to and `resourceId` the resource itself, so a workspace's
+ * shares invalidate together under a single prefix.
*/
export const shareKeys = {
all: ['publicShares'] as const,
details: () => [...shareKeys.all, 'detail'] as const,
- detail: (workspaceId: string, fileId: string) =>
- [...shareKeys.details(), workspaceId, fileId] as const,
+ detail: (resourceType: ShareResourceType, scopeId: string, resourceId: string) =>
+ [...shareKeys.details(), resourceType, scopeId, resourceId] as const,
}
async function fetchFileShare(
@@ -38,31 +46,68 @@ async function fetchFileShare(
return data.share
}
-export function useFileShare(workspaceId: string, fileId: string, options?: { enabled?: boolean }) {
+/**
+ * The share record for any shareable resource. One hook serves every resource
+ * family so the shared share modal cannot fork per resource: the query key and
+ * the fetch both branch on the same `resourceType`, which is part of the key.
+ */
+export function useResourceShare(
+ resourceType: ShareableResourceType,
+ workspaceId: string,
+ resourceId: string,
+ options?: { enabled?: boolean }
+) {
return useQuery({
- queryKey: shareKeys.detail(workspaceId, fileId),
- queryFn: ({ signal }) => fetchFileShare(workspaceId, fileId, signal),
- enabled: Boolean(workspaceId) && Boolean(fileId) && (options?.enabled ?? true),
- staleTime: FILE_SHARE_STALE_TIME,
+ queryKey: shareKeys.detail(resourceType, workspaceId, resourceId),
+ queryFn: ({ signal }) => fetchFileShare(workspaceId, resourceId, signal),
+ enabled: Boolean(workspaceId) && Boolean(resourceId) && (options?.enabled ?? true),
+ staleTime: RESOURCE_SHARE_STALE_TIME,
})
}
-interface UpsertFileShareVariables extends UpsertFileShareBody {
+interface UpsertResourceShareVariables extends UpsertFileShareBody {
+ resourceType: ShareableResourceType
workspaceId: string
- fileId: string
+ resourceId: string
}
-export function useUpsertFileShare() {
+/**
+ * Saves a share for any shareable resource. On success the detail cache is
+ * seeded with the saved record, and the files list is refreshed because its rows
+ * carry a share badge.
+ */
+export function useUpsertResourceShare() {
const queryClient = useQueryClient()
return useMutation({
- mutationFn: ({ workspaceId, fileId, ...body }: UpsertFileShareVariables) =>
+ mutationFn: ({
+ resourceType,
+ workspaceId,
+ resourceId,
+ ...body
+ }: UpsertResourceShareVariables) =>
requestJson(upsertFileShareContract, {
- params: { id: workspaceId, fileId },
+ params: { id: workspaceId, fileId: resourceId },
body,
}),
- onSuccess: (data, { workspaceId, fileId }) => {
- queryClient.setQueryData(shareKeys.detail(workspaceId, fileId), data.share)
- queryClient.invalidateQueries({ queryKey: workspaceFilesKeys.workspaceLists(workspaceId) })
+ onSuccess: (data, { resourceType, workspaceId, resourceId }) => {
+ queryClient.setQueryData(shareKeys.detail(resourceType, workspaceId, resourceId), data.share)
+ },
+ /**
+ * Both the share record and the file row's share badge are reconciled on
+ * failure: a partial failure — share written, response lost — would
+ * otherwise leave the modal showing a pre-save record and the badge stale
+ * until something else happened to invalidate them. On success `onSuccess`
+ * already adopted the server's record, so only the list needs refreshing.
+ */
+ onSettled: (_data, error, { resourceType, workspaceId, resourceId }) => {
+ if (error) {
+ queryClient.invalidateQueries({
+ queryKey: shareKeys.detail(resourceType, workspaceId, resourceId),
+ })
+ }
+ if (resourceType === 'file') {
+ queryClient.invalidateQueries({ queryKey: workspaceFilesKeys.workspaceLists(workspaceId) })
+ }
},
onError: (error) => {
toast.error(error.message)
diff --git a/apps/sim/hooks/queries/tables.ts b/apps/sim/hooks/queries/tables.ts
index a1f13eba635..8fdadaeaa31 100644
--- a/apps/sim/hooks/queries/tables.ts
+++ b/apps/sim/hooks/queries/tables.ts
@@ -16,12 +16,7 @@ import {
useQueryClient,
} from '@tanstack/react-query'
import { useRouter } from 'next/navigation'
-import {
- ApiClientError,
- extractValidationIssues,
- isApiClientError,
- isValidationError,
-} from '@/lib/api/client/errors'
+import { ApiClientError, isApiClientError, isValidationError } from '@/lib/api/client/errors'
import { requestJson } from '@/lib/api/client/request'
import type { ContractJsonResponse } from '@/lib/api/contracts'
import {
@@ -109,6 +104,10 @@ import {
} from '@/lib/table/deps'
import { runUploadStrategy } from '@/lib/uploads/client/direct-upload'
import { useTimezone } from '@/hooks/queries/general-settings'
+import {
+ toastMutationError,
+ toastNonValidationError,
+} from '@/hooks/queries/utils/mutation-error-toast'
import {
TABLE_LIST_STALE_TIME,
TABLE_VIEWS_STALE_TIME,
@@ -539,9 +538,7 @@ export function useCreateTable(workspaceId: string) {
},
// Unlike row writes, table naming has no inline validation surface — the
// issue message (e.g. the NAME_PATTERN rule) must reach the user as a toast.
- onError: (error) => {
- toast.error(extractValidationIssues(error)[0]?.message ?? error.message, { duration: 5000 })
- },
+ onError: toastMutationError,
onSettled: () => {
queryClient.invalidateQueries({ queryKey: tableKeys.lists() })
},
@@ -563,8 +560,7 @@ export function useAddTableColumn({ workspaceId, tableId }: RowMutationContext)
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateTableSchemaOnly(queryClient, tableId)
@@ -587,9 +583,7 @@ export function useRenameTable(workspaceId: string) {
},
// Inline rename reverts the field on failure with no message of its own, so
// the validation issue (e.g. the NAME_PATTERN rule) must surface as a toast.
- onError: (error) => {
- toast.error(extractValidationIssues(error)[0]?.message ?? error.message, { duration: 5000 })
- },
+ onError: toastMutationError,
onSettled: (_data, _error, variables) => {
queryClient.invalidateQueries({ queryKey: tableKeys.detail(variables.tableId) })
queryClient.invalidateQueries({ queryKey: tableKeys.lists() })
@@ -698,8 +692,7 @@ export function useDeleteTable(workspaceId: string) {
},
onError: (error, tableId) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: (_data, _error, tableId) => {
queryClient.invalidateQueries({ queryKey: tableKeys.lists() })
@@ -1067,8 +1060,7 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
queryClient.setQueryData(tableKeys.activeDispatches(tableId), context.runStateSnapshot)
}
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
})
}
@@ -1141,8 +1133,7 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
queryClient.setQueryData(tableKeys.activeDispatches(tableId), context.runStateSnapshot)
}
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
})
}
@@ -1162,8 +1153,7 @@ export function useDeleteTableRow({ workspaceId, tableId }: RowMutationContext)
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateRowCount(queryClient, tableId)
@@ -1211,8 +1201,7 @@ export function useDeleteTableRows({ workspaceId, tableId }: RowMutationContext)
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateRowCount(queryClient, tableId)
@@ -1313,8 +1302,7 @@ export function useDeleteTableRowsAsync({ workspaceId, tableId }: RowMutationCon
queryClient.setQueryData(tableKeys.detail(tableId), context.previousDetail)
}
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
})
}
@@ -1382,8 +1370,7 @@ export function useUpdateColumn({ workspaceId, tableId }: RowMutationContext) {
queryClient.setQueryData(tableKeys.detail(tableId), context.previousDetail)
}
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: (_data, _error, variables, context) => {
// A type change, a select single↔multi toggle, or removing an option
@@ -1705,8 +1692,7 @@ export function useRestoreTable() {
},
onError: (error, tableId) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSuccess: (response, tableId) => {
queryClient.setQueryData(tableKeys.detail(tableId), response.data.table)
@@ -2067,8 +2053,7 @@ export function useExportTableAsync({ workspaceId, tableId }: RowMutationContext
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
})
}
@@ -2179,8 +2164,7 @@ export function useDeleteColumn({ workspaceId, tableId }: RowMutationContext) {
}
}
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateTableSchema(queryClient, tableId)
@@ -2480,8 +2464,7 @@ export function useAddWorkflowGroup({ workspaceId, tableId }: RowMutationContext
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateTableSchema(queryClient, tableId)
@@ -2514,8 +2497,7 @@ export function useUpdateWorkflowGroup({ workspaceId, tableId }: RowMutationCont
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateTableSchema(queryClient, tableId)
@@ -2539,8 +2521,7 @@ export function useDeleteWorkflowGroup({ workspaceId, tableId }: RowMutationCont
},
onError: (error) => {
if (handleTableLockRejection(error, queryClient, tableId)) return
- if (isValidationError(error)) return
- toast.error(error.message, { duration: 5000 })
+ toastNonValidationError(error)
},
onSettled: () => {
invalidateTableSchema(queryClient, tableId)
diff --git a/apps/sim/hooks/queries/utils/mutation-error-toast.ts b/apps/sim/hooks/queries/utils/mutation-error-toast.ts
new file mode 100644
index 00000000000..e0072261d81
--- /dev/null
+++ b/apps/sim/hooks/queries/utils/mutation-error-toast.ts
@@ -0,0 +1,24 @@
+import { toast } from '@sim/emcn'
+import { extractValidationIssues, isValidationError } from '@/lib/api/client/errors'
+
+const ERROR_TOAST_DURATION_MS = 5000
+
+/**
+ * Toasts a mutation failure for surfaces with no inline validation UI: the
+ * first validation issue's message when the error is a validation failure,
+ * otherwise the error's own message.
+ */
+export function toastMutationError(error: Error): void {
+ toast.error(extractValidationIssues(error)[0]?.message ?? error.message, {
+ duration: ERROR_TOAST_DURATION_MS,
+ })
+}
+
+/**
+ * Toasts a mutation failure unless it is a validation error — for mutations
+ * whose validation failures are surfaced inline by the calling UI.
+ */
+export function toastNonValidationError(error: Error): void {
+ if (isValidationError(error)) return
+ toast.error(error.message, { duration: ERROR_TOAST_DURATION_MS })
+}
diff --git a/apps/sim/hooks/queries/workspace-files.test.tsx b/apps/sim/hooks/queries/workspace-files.test.tsx
index db51e9fc452..94dfb9ad2bb 100644
--- a/apps/sim/hooks/queries/workspace-files.test.tsx
+++ b/apps/sim/hooks/queries/workspace-files.test.tsx
@@ -13,6 +13,9 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useWorkspaceFileContent } from '@/hooks/queries/workspace-files'
+import { workspaceSource } from '@/resources'
+
+const SOURCE = workspaceSource({ kind: 'file', workspaceId: 'ws-1', resourceId: 'file-1' })
let fetchCount = 0
@@ -40,7 +43,7 @@ function renderContentHook(options?: {
const root: Root = createRoot(container)
function Probe() {
- useWorkspaceFileContent('ws-1', 'file-1', 'workspace/ws-1/123-abc-doc.md', false, options)
+ useWorkspaceFileContent(SOURCE, 'file-1', 'workspace/ws-1/123-abc-doc.md', false, options)
return null
}
diff --git a/apps/sim/hooks/queries/workspace-files.ts b/apps/sim/hooks/queries/workspace-files.ts
index ad49ba3e283..859a9f3d727 100644
--- a/apps/sim/hooks/queries/workspace-files.ts
+++ b/apps/sim/hooks/queries/workspace-files.ts
@@ -23,7 +23,8 @@ import {
} from '@/lib/uploads/client/direct-upload'
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
import type { UserFile } from '@/executor/types'
-import { useFileContentSource } from '@/hooks/use-file-content-source'
+import type { ResourceSource } from '@/resources'
+import { fileCacheScope, fileContentUrl } from '@/resources/file-source'
const logger = createLogger('WorkspaceFilesQuery')
@@ -150,18 +151,18 @@ async function fetchWorkspaceFileContent(url: string, signal?: AbortSignal): Pro
* as it flips — no re-render required.
*/
export function useWorkspaceFileContent(
- workspaceId: string,
+ source: ResourceSource<'file'>,
fileId: string,
key: string,
raw?: boolean,
options?: { refetchInterval?: number | false | (() => number | false) }
) {
- const source = useFileContentSource()
+ const scope = fileCacheScope(source)
return useQuery({
- queryKey: workspaceFilesKeys.content(workspaceId, fileId, raw ? 'raw' : 'text', key),
+ queryKey: workspaceFilesKeys.content(scope, fileId, raw ? 'raw' : 'text', key),
queryFn: ({ signal }) =>
- fetchWorkspaceFileContent(source.buildUrl(key, { raw, bust: true }), signal),
- enabled: !!workspaceId && !!fileId && !!key,
+ fetchWorkspaceFileContent(fileContentUrl(source, key, { raw, bust: true }), signal),
+ enabled: !!scope && !!fileId && !!key,
staleTime: WORKSPACE_FILE_CONTENT_STALE_TIME,
refetchOnWindowFocus: 'always',
refetchInterval: options?.refetchInterval ?? false,
@@ -218,20 +219,20 @@ async function fetchWorkspaceFileBinary(
* open, keyed to the current content rather than a stale cached entry).
*/
export function useWorkspaceFileBinary(
- workspaceId: string,
+ source: ResourceSource<'file'>,
fileId: string,
key: string,
options?: { enabled?: boolean; version?: string | number }
) {
- const source = useFileContentSource()
+ const scope = fileCacheScope(source)
return useQuery({
queryKey:
options?.version != null
- ? [...workspaceFilesKeys.content(workspaceId, fileId, 'binary', key), options.version]
- : workspaceFilesKeys.content(workspaceId, fileId, 'binary', key),
+ ? [...workspaceFilesKeys.content(scope, fileId, 'binary', key), options.version]
+ : workspaceFilesKeys.content(scope, fileId, 'binary', key),
queryFn: ({ signal }) =>
fetchWorkspaceFileBinary(
- source.buildUrl(key, { version: options?.version, bust: true }),
+ fileContentUrl(source, key, { version: options?.version, bust: true }),
options?.version,
signal
),
@@ -239,7 +240,7 @@ export function useWorkspaceFileBinary(
// content) so we don't 409-poll the serve route for a generated doc whose
// compiled artifact hasn't been written yet — the doc is fetched once, when
// it's actually ready, instead of hammering the serve URL through generation.
- enabled: !!workspaceId && !!fileId && !!key && (options?.enabled ?? true),
+ enabled: !!scope && !!fileId && !!key && (options?.enabled ?? true),
staleTime: WORKSPACE_FILE_BINARY_STALE_TIME,
refetchOnWindowFocus: 'always',
placeholderData: keepPreviousData,
diff --git a/apps/sim/hooks/use-drag-reorder.ts b/apps/sim/hooks/use-drag-reorder.ts
new file mode 100644
index 00000000000..f54646e69e8
--- /dev/null
+++ b/apps/sim/hooks/use-drag-reorder.ts
@@ -0,0 +1,105 @@
+'use client'
+
+import { type DragEvent, useCallback, useState } from 'react'
+
+/** Props spread onto one reorderable row. */
+export interface DragReorderItemProps {
+ draggable: boolean
+ onDragStart: (event: DragEvent) => void
+ onDragEnd: () => void
+ onDragOver: (event: DragEvent) => void
+ onDrop: (event: DragEvent) => void
+}
+
+export interface DragReorder {
+ /** Index being dragged, or `null` when idle — for dimming the source row. */
+ draggingIndex: number | null
+ /** Index currently hovered by the drag, or `null` — for the drop indicator. */
+ overIndex: number | null
+ itemProps: (index: number) => DragReorderItemProps
+}
+
+/**
+ * Reorder a list by dragging its rows, using native HTML5 drag-and-drop.
+ *
+ * Native DnD rather than a pointer-event implementation for one concrete
+ * reason: the browser auto-scrolls the nearest scrollable ancestor while a
+ * drag is near its edge. A hand-rolled version has to reimplement that, and a
+ * form long enough to need reordering is exactly the one that needs to scroll
+ * while doing it.
+ *
+ * Shared by both surfaces that reorder form fields — the module on the canvas
+ * and the inspector panel — so the two behave identically rather than each
+ * growing its own drag state.
+ *
+ * @param onReorder receives source and destination indices. Called only for a
+ * real move, so a drop on the row being dragged is already filtered out.
+ * @param enabled `false` leaves every row inert — a read-only viewer gets no
+ * drag affordance at all rather than one that silently does nothing.
+ */
+export function useDragReorder(
+ onReorder: (from: number, to: number) => void,
+ enabled = true
+): DragReorder {
+ const [draggingIndex, setDraggingIndex] = useState(null)
+ const [overIndex, setOverIndex] = useState(null)
+
+ const itemProps = useCallback(
+ (index: number): DragReorderItemProps => ({
+ draggable: enabled,
+ onDragStart: (event) => {
+ if (!enabled) {
+ event.preventDefault()
+ return
+ }
+ /**
+ * A reorderable row can sit inside another draggable — a form field
+ * inside an interface module's cell. Without this the native event
+ * bubbles, the cell overwrites the drag payload with its own module id,
+ * and dropping the field relocates the whole module instead.
+ */
+ event.stopPropagation()
+ event.dataTransfer.effectAllowed = 'move'
+ /** Firefox refuses to start a drag with an empty data transfer. */
+ event.dataTransfer.setData('text/plain', String(index))
+ setDraggingIndex(index)
+ },
+ /** Fires for both a completed and a cancelled drag — the only teardown needed. */
+ onDragEnd: () => {
+ setDraggingIndex(null)
+ setOverIndex(null)
+ },
+ onDragOver: (event) => {
+ if (draggingIndex === null) return
+ event.stopPropagation()
+ event.preventDefault()
+ event.dataTransfer.dropEffect = 'move'
+ setOverIndex((previous) => (previous === index ? previous : index))
+ },
+ onDrop: (event) => {
+ event.stopPropagation()
+ event.preventDefault()
+ const from = draggingIndex
+ setDraggingIndex(null)
+ setOverIndex(null)
+ if (from === null || from === index) return
+ onReorder(from, index)
+ },
+ }),
+ [enabled, draggingIndex, onReorder]
+ )
+
+ return { draggingIndex, overIndex, itemProps }
+}
+
+/**
+ * Moves `from` to `to`, returning a new array. The one definition of what a
+ * reorder does, so the canvas and the inspector cannot disagree about where a
+ * dropped field lands.
+ */
+export function reorderList(items: readonly T[], from: number, to: number): T[] {
+ const next = [...items]
+ const [moved] = next.splice(from, 1)
+ next.splice(to, 0, moved)
+ return next
+}
diff --git a/apps/sim/hooks/use-execution-stream.ts b/apps/sim/hooks/use-execution-stream.ts
index 100b6c0e649..bd17b558921 100644
--- a/apps/sim/hooks/use-execution-stream.ts
+++ b/apps/sim/hooks/use-execution-stream.ts
@@ -203,6 +203,23 @@ export interface ExecuteStreamOptions {
parallels?: Record
}
stopAfterBlockId?: string
+ /**
+ * Isolates this run from other runs of the same workflow. Streams are keyed
+ * per workflow by default, so a second `execute` for the same workflow aborts
+ * the first — correct for the editor, where one workflow has one run, but
+ * wrong for surfaces that mount several independent runners against the same
+ * workflow (e.g. two interface chat modules wired to it with different output
+ * selections). Supplying a key confines both the pre-flight abort and
+ * {@link useExecutionStream.cancelExecute} to that key alone.
+ */
+ streamKey?: string
+ /**
+ * Overrides the default `/api/workflows/{workflowId}/execute` URL. The public
+ * interface chat posts to its token-scoped route, which derives the workflow
+ * and the selected outputs from the stored layout. When set, `workflowId` is
+ * used only as the abort-controller key.
+ */
+ endpoint?: string
onExecutionId?: (executionId: string) => void
callbacks?: ExecutionStreamCallbacks
}
@@ -232,8 +249,8 @@ export interface ReconnectStreamOptions {
*/
const sharedAbortControllers = new Map()
-function executeStreamKey(workflowId: string): string {
- return `${workflowId}:execute`
+function executeStreamKey(workflowId: string, streamKey?: string): string {
+ return `${workflowId}:execute:${streamKey ?? 'default'}`
}
function reconnectStreamKey(workflowId: string, executionId: string): string {
@@ -262,18 +279,22 @@ function abortWorkflowStreams(workflowId: string): void {
*/
export function useExecutionStream() {
const execute = useCallback(async (options: ExecuteStreamOptions) => {
- const { workflowId, callbacks = {}, onExecutionId, ...payload } = options
+ const { workflowId, streamKey, endpoint, callbacks = {}, onExecutionId, ...payload } = options
- abortWorkflowStreams(workflowId)
+ const controllerKey = executeStreamKey(workflowId, streamKey)
+ if (streamKey) {
+ abortStream(controllerKey)
+ } else {
+ abortWorkflowStreams(workflowId)
+ }
const abortController = new AbortController()
- const streamKey = executeStreamKey(workflowId)
- sharedAbortControllers.set(streamKey, abortController)
+ sharedAbortControllers.set(controllerKey, abortController)
let serverExecutionId: string | undefined
try {
// boundary-raw-fetch: workflow execute endpoint returns an SSE stream consumed via response.body.getReader() and processSSEStream; also reads the X-Execution-Id response header
- const response = await fetch(`/api/workflows/${workflowId}/execute`, {
+ const response = await fetch(endpoint ?? `/api/workflows/${workflowId}/execute`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -338,8 +359,8 @@ export function useExecutionStream() {
}
throw error
} finally {
- if (sharedAbortControllers.get(streamKey) === abortController) {
- sharedAbortControllers.delete(streamKey)
+ if (sharedAbortControllers.get(controllerKey) === abortController) {
+ sharedAbortControllers.delete(controllerKey)
}
}
}, [])
@@ -488,8 +509,12 @@ export function useExecutionStream() {
abortStream(reconnectStreamKey(workflowId, executionId))
}, [])
- const cancelExecute = useCallback((workflowId: string) => {
- abortStream(executeStreamKey(workflowId))
+ /**
+ * Aborts one execute stream. Pass the same `streamKey` the run was started
+ * with; omit it to abort the default (unkeyed) run.
+ */
+ const cancelExecute = useCallback((workflowId: string, streamKey?: string) => {
+ abortStream(executeStreamKey(workflowId, streamKey))
}, [])
return {
diff --git a/apps/sim/hooks/use-file-content-source.tsx b/apps/sim/hooks/use-file-content-source.tsx
deleted file mode 100644
index bd9552d8e7e..00000000000
--- a/apps/sim/hooks/use-file-content-source.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-'use client'
-
-import { createContext, useContext } from 'react'
-import {
- type EmbeddedFileRef,
- extractEmbeddedFileRef,
-} from '@/lib/uploads/utils/embedded-image-ref'
-
-export interface FileContentUrlOptions {
- /** Request the uncompiled source instead of the rendered/compiled bytes. */
- raw?: boolean
- /** Content version (e.g. the record's `updatedAt`) — makes the URL cacheable/immutable. */
- version?: string | number
- /** Append a timestamp cache-buster when there is no `version`. */
- bust?: boolean
-}
-
-function inlineRefQuery(ref: NonNullable): string {
- return 'key' in ref
- ? `key=${encodeURIComponent(ref.key)}`
- : `fileId=${encodeURIComponent(ref.fileId)}`
-}
-
-/**
- * Seam for "where do a file's bytes come from". The in-app viewer resolves the
- * auth-gated workspace serve URL; the public share page swaps in a token-scoped
- * URL. Renderers and the binary/text query hooks build their fetch URL through
- * this source so the same components work in both contexts.
- */
-export interface FileContentSource {
- buildUrl: (key: string, opts?: FileContentUrlOptions) => string
- /**
- * Map an embedded image `src` to a display URL scoped to the current context: the in-app source
- * points at the workspace-scoped inline route, the public source at the token-scoped cascade route.
- * Non-workspace srcs (external, `data:`, public assets) pass through unchanged.
- */
- resolveImageSrc: (src: string | undefined) => string | undefined
-}
-
-function buildServeUrl(key: string, opts?: FileContentUrlOptions): string {
- const base = `/api/files/serve/${encodeURIComponent(key)}?context=workspace`
- const params: string[] = []
- if (opts?.version != null) params.push(`v=${encodeURIComponent(String(opts.version))}`)
- else if (opts?.bust) params.push(`t=${Date.now()}`)
- if (opts?.raw) params.push('raw=1')
- return params.length > 0 ? `${base}&${params.join('&')}` : base
-}
-
-/** Build a source whose embeds resolve through `inlineBase` (the workspace- or token-scoped inline route). */
-function inlineImageSource(
- buildUrl: FileContentSource['buildUrl'],
- inlineBase: string
-): FileContentSource {
- return {
- buildUrl,
- resolveImageSrc: (src) => {
- if (!src) return src
- const ref = extractEmbeddedFileRef(src)
- return ref ? `${inlineBase}?${inlineRefQuery(ref)}` : src
- },
- }
-}
-
-/**
- * In-app source scoped to one workspace. Direct file bytes come from the workspace serve URL; embedded
- * images route through `/api/workspaces/{workspaceId}/files/inline`, which resolves a reference only
- * within this workspace — a cross-workspace embed 404s and does not render.
- */
-export function createWorkspaceFileContentSource(workspaceId: string): FileContentSource {
- return inlineImageSource(buildServeUrl, `/api/workspaces/${workspaceId}/files/inline`)
-}
-
-/**
- * Public share source. Direct file bytes come from the token content URL; embedded images route through
- * `/api/files/public/{token}/inline`, which serves them only when referenced by the shared document and
- * in its workspace.
- */
-export function createPublicFileContentSource(
- token: string,
- contentUrl: string
-): FileContentSource {
- return inlineImageSource(() => contentUrl, `/api/files/public/${token}/inline`)
-}
-
-/**
- * Context default for components rendered outside a {@link FileContentSourceProvider}: serve URLs for
- * direct bytes, embeds passed through unchanged. The file viewer always provides a workspace- or
- * token-scoped source, so embeds resolve through the scoped inline routes there.
- */
-export const workspaceFileContentSource: FileContentSource = {
- buildUrl: buildServeUrl,
- resolveImageSrc: (src) => src,
-}
-
-const FileContentSourceContext = createContext(workspaceFileContentSource)
-
-export const FileContentSourceProvider = FileContentSourceContext.Provider
-
-export function useFileContentSource(): FileContentSource {
- return useContext(FileContentSourceContext)
-}
diff --git a/apps/sim/hooks/use-share-modal-state.test.tsx b/apps/sim/hooks/use-share-modal-state.test.tsx
new file mode 100644
index 00000000000..4e7d4a87fe9
--- /dev/null
+++ b/apps/sim/hooks/use-share-modal-state.test.tsx
@@ -0,0 +1,327 @@
+/**
+ * @vitest-environment jsdom
+ *
+ * Every share modal renders from this state machine, so the pre-reserved token,
+ * the null-until-touched drafts, the org-policy gates, and the save payload are
+ * pinned here once rather than per resource family.
+ */
+import { act } from 'react'
+import { createRoot, type Root } from 'react-dom/client'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import type { ShareRecord } from '@/lib/api/contracts/public-shares'
+
+/**
+ * `isSsoEnabled` is a module-level const (evaluated at import), so it is mocked
+ * behind a getter the tests can flip rather than a fixed value.
+ */
+const { ssoFlag } = vi.hoisted(() => ({ ssoFlag: { enabled: false } }))
+
+vi.mock('@/lib/core/config/env-flags', () => ({
+ get isSsoEnabled() {
+ return ssoFlag.enabled
+ },
+}))
+
+vi.mock('@/lib/public-shares/urls', () => ({
+ buildShareUrl: (_resourceType: string, token: string) => `https://sim.ai/f/${token}`,
+}))
+
+import {
+ type UseShareModalStateArgs,
+ type UseShareModalStateResult,
+ useShareModalState,
+} from '@/hooks/use-share-modal-state'
+
+const ALLOW_ALL = { disablePublicSharing: false, allowedAuthTypes: null }
+
+const BASE_ARGS: UseShareModalStateArgs = {
+ resourceType: 'file',
+ saved: null,
+ isFetched: true,
+ policy: ALLOW_ALL,
+}
+
+function buildShare(overrides: Partial = {}): ShareRecord {
+ return {
+ id: 'sh_1',
+ token: 'tok_saved',
+ url: 'https://sim.ai/f/tok_saved',
+ isActive: true,
+ resourceType: 'file',
+ resourceId: 'file-1',
+ authType: 'public',
+ hasPassword: false,
+ allowedEmails: [],
+ ...overrides,
+ }
+}
+
+interface Harness {
+ current: UseShareModalStateResult
+ rerender: (patch: Partial) => void
+ /** Runs a state update inside `act` and returns whatever the callback produced. */
+ run: (fn: (state: UseShareModalStateResult) => T) => T
+}
+
+function render(overrides: Partial = {}): Harness {
+ ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
+ const container = document.createElement('div')
+ const root: Root = createRoot(container)
+ let result: UseShareModalStateResult | undefined
+ let args: UseShareModalStateArgs = { ...BASE_ARGS, ...overrides }
+
+ function Probe({ hookArgs }: { hookArgs: UseShareModalStateArgs }) {
+ result = useShareModalState(hookArgs)
+ return null
+ }
+
+ const paint = () => act(() => root.render( ))
+ paint()
+
+ return {
+ get current(): UseShareModalStateResult {
+ if (!result) throw new Error('Hook result is not ready')
+ return result
+ },
+ rerender(patch) {
+ args = { ...args, ...patch }
+ paint()
+ },
+ run(fn) {
+ let out: ReturnType
+ act(() => {
+ if (!result) throw new Error('Hook result is not ready')
+ out = fn(result)
+ })
+ return out as ReturnType
+ },
+ }
+}
+
+describe('useShareModalState', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ ssoFlag.enabled = false
+ })
+
+ describe('mode derivation', () => {
+ it('starts private when nothing is shared', () => {
+ const hook = render()
+ expect(hook.current.mode).toBe('private')
+ expect(hook.current.isDirty).toBe(false)
+ })
+
+ it('reflects the saved auth mode', () => {
+ const hook = render({ saved: buildShare({ authType: 'password', hasPassword: true }) })
+ expect(hook.current.mode).toBe('password')
+ })
+
+ it('reads an inactive share as private even when an auth type is stored', () => {
+ const hook = render({
+ saved: buildShare({ isActive: false, authType: 'password', hasPassword: true }),
+ })
+ expect(hook.current.mode).toBe('private')
+ })
+
+ /**
+ * Drafts stay `null` until touched so each control keeps reflecting the
+ * authoritative saved state even when the share query resolves after mount.
+ */
+ it('adopts a share that arrives after mount', () => {
+ const hook = render()
+ expect(hook.current.mode).toBe('private')
+ hook.rerender({ saved: buildShare({ authType: 'email', allowedEmails: ['a@b.com'] }) })
+ expect(hook.current.mode).toBe('email')
+ expect(hook.current.emails).toEqual(['a@b.com'])
+ })
+
+ it('keeps a touched draft when a later fetch resolves', () => {
+ const hook = render()
+ hook.run((state) => state.setMode('password'))
+ hook.rerender({ saved: buildShare({ authType: 'public' }) })
+ expect(hook.current.mode).toBe('password')
+ })
+ })
+
+ describe('share link', () => {
+ it('withholds the link until the share query settles', () => {
+ const hook = render({ isFetched: false })
+ expect(hook.current.shareUrl).toBeNull()
+ })
+
+ it('shows a pre-reserved link before the first save', () => {
+ const hook = render()
+ expect(hook.current.shareUrl).toMatch(/^https:\/\/sim\.ai\/f\/.+/)
+ })
+
+ it('prefers the saved url once a share exists', () => {
+ const hook = render({ saved: buildShare() })
+ expect(hook.current.shareUrl).toBe('https://sim.ai/f/tok_saved')
+ })
+
+ it('keeps the reserved token stable across re-renders', () => {
+ const hook = render()
+ const first = hook.current.shareUrl
+ hook.rerender({})
+ expect(hook.current.shareUrl).toBe(first)
+ })
+ })
+
+ describe('validation gates', () => {
+ it('blocks saving a password share with no password', () => {
+ const hook = render()
+ hook.run((state) => state.setMode('password'))
+ expect(hook.current.passwordMissing).toBe(true)
+ expect(hook.current.canSave).toBe(false)
+ hook.run((state) => state.setPassword('hunter22'))
+ expect(hook.current.passwordMissing).toBe(false)
+ expect(hook.current.canSave).toBe(true)
+ })
+
+ it('accepts switching to password when a secret is already stored', () => {
+ const hook = render({
+ saved: buildShare({ isActive: false, authType: 'password', hasPassword: true }),
+ })
+ hook.run((state) => state.setMode('password'))
+ expect(hook.current.passwordMissing).toBe(false)
+ expect(hook.current.canSave).toBe(true)
+ })
+
+ it.each(['email', 'sso'] as const)('blocks saving a %s share with no allow-list', (mode) => {
+ ssoFlag.enabled = true
+ const hook = render()
+ hook.run((state) => state.setMode(mode))
+ expect(hook.current.emailsMissing).toBe(true)
+ expect(hook.current.canSave).toBe(false)
+ hook.run((state) => state.setEmails(['a@b.com']))
+ expect(hook.current.emailsMissing).toBe(false)
+ expect(hook.current.canSave).toBe(true)
+ })
+
+ it('reads the saved allow-list until the draft is touched', () => {
+ const hook = render({
+ saved: buildShare({ authType: 'email', allowedEmails: ['a@b.com', 'c@d.com'] }),
+ })
+ expect(hook.current.emails).toEqual(['a@b.com', 'c@d.com'])
+ expect(hook.current.isDirty).toBe(false)
+ hook.run((state) => state.setEmails(['c@d.com']))
+ expect(hook.current.emails).toEqual(['c@d.com'])
+ expect(hook.current.isDirty).toBe(true)
+ })
+
+ it('is not dirty when the draft allow-list matches the saved one', () => {
+ const hook = render({
+ saved: buildShare({ authType: 'email', allowedEmails: ['a@b.com'] }),
+ })
+ hook.run((state) => state.setEmails(['a@b.com']))
+ expect(hook.current.isDirty).toBe(false)
+ })
+ })
+
+ describe('org policy', () => {
+ it('blocks enabling a new share when public sharing is disabled', () => {
+ const hook = render({ policy: { disablePublicSharing: true, allowedAuthTypes: null } })
+ hook.run((state) => state.setMode('public'))
+ expect(hook.current.enableBlockedByPolicy).toBe(true)
+ expect(hook.current.canSave).toBe(false)
+ })
+
+ it('still allows going private when public sharing is disabled', () => {
+ const hook = render({
+ saved: buildShare(),
+ policy: { disablePublicSharing: true, allowedAuthTypes: null },
+ })
+ hook.run((state) => state.setMode('private'))
+ expect(hook.current.canSave).toBe(true)
+ expect(hook.current.buildSavePayload().isActive).toBe(false)
+ })
+
+ it('hides auth modes the org disallows', () => {
+ const hook = render({
+ policy: { disablePublicSharing: false, allowedAuthTypes: ['password'] },
+ })
+ expect(hook.current.availableModes).toEqual(['private', 'password'])
+ })
+
+ it('keeps a saved-but-now-disallowed mode visible', () => {
+ const hook = render({
+ saved: buildShare({ authType: 'public' }),
+ policy: { disablePublicSharing: false, allowedAuthTypes: ['password'] },
+ })
+ expect(hook.current.availableModes).toContain('public')
+ expect(hook.current.modeDisallowed).toBe(true)
+ })
+
+ it('omits sso unless the deployment enables it', () => {
+ expect(render().current.availableModes).not.toContain('sso')
+ ssoFlag.enabled = true
+ expect(render().current.availableModes).toContain('sso')
+ })
+ })
+
+ describe('save payload', () => {
+ it('sends the reserved token only when creating the row', () => {
+ const hook = render()
+ hook.run((state) => state.setMode('public'))
+ expect(hook.current.buildSavePayload()).toEqual({
+ isActive: true,
+ authType: 'public',
+ token: expect.any(String),
+ })
+ })
+
+ it('omits the token for an existing share', () => {
+ const hook = render({ saved: buildShare({ authType: 'public' }) })
+ hook.run((state) => state.setMode('password'))
+ hook.run((state) => state.setPassword('hunter22'))
+ expect(hook.current.buildSavePayload()).toEqual({
+ isActive: true,
+ authType: 'password',
+ password: 'hunter22',
+ token: undefined,
+ })
+ })
+
+ it('sends the allow-list for email and sso', () => {
+ const hook = render({ saved: buildShare({ authType: 'public' }) })
+ hook.run((state) => state.setMode('email'))
+ hook.run((state) => state.setEmails(['a@b.com']))
+ expect(hook.current.buildSavePayload()).toEqual({
+ isActive: true,
+ authType: 'email',
+ allowedEmails: ['a@b.com'],
+ token: undefined,
+ })
+ })
+
+ it('sends isActive false with no auth config when going private', () => {
+ const hook = render({ saved: buildShare({ authType: 'password', hasPassword: true }) })
+ hook.run((state) => state.setMode('private'))
+ const payload = hook.current.buildSavePayload()
+ expect(payload.isActive).toBe(false)
+ expect(payload.authType).toBeUndefined()
+ expect(payload.password).toBeUndefined()
+ })
+
+ it('never sends a whitespace-only password', () => {
+ const hook = render()
+ hook.run((state) => state.setMode('password'))
+ hook.run((state) => state.setPassword(' '))
+ expect(hook.current.passwordMissing).toBe(true)
+ expect(hook.current.buildSavePayload().password).toBeUndefined()
+ })
+ })
+
+ it('reset returns every draft to the saved state', () => {
+ const hook = render({ saved: buildShare({ authType: 'public' }) })
+ hook.run((state) => state.setMode('email'))
+ hook.run((state) => state.setEmails(['a@b.com']))
+ hook.run((state) => state.setPassword('hunter22'))
+ expect(hook.current.isDirty).toBe(true)
+ hook.run((state) => state.reset())
+ expect(hook.current.mode).toBe('public')
+ expect(hook.current.emails).toEqual([])
+ expect(hook.current.password).toBe('')
+ expect(hook.current.isDirty).toBe(false)
+ })
+})
diff --git a/apps/sim/hooks/use-share-modal-state.ts b/apps/sim/hooks/use-share-modal-state.ts
new file mode 100644
index 00000000000..4dc811d83b1
--- /dev/null
+++ b/apps/sim/hooks/use-share-modal-state.ts
@@ -0,0 +1,199 @@
+import { useCallback, useState } from 'react'
+import { generateShortId } from '@sim/utils/id'
+import type {
+ ShareAuthType,
+ ShareRecord,
+ ShareResourceType,
+} from '@/lib/api/contracts/public-shares'
+import { isSsoEnabled } from '@/lib/core/config/env-flags'
+import { buildShareUrl } from '@/lib/public-shares/urls'
+
+/** Not shared at all, or one of the four public share auth modes. */
+export type ShareAccessMode = 'private' | ShareAuthType
+
+/** ButtonGroup labels for {@link ShareAccessMode}. Shared so every share modal reads identically. */
+export const SHARE_ACCESS_LABELS: Record = {
+ private: 'Private',
+ public: 'Public',
+ password: 'Password',
+ email: 'Email',
+ sso: 'SSO',
+}
+
+/** The upsert payload a share modal sends, minus the resource identifiers. */
+export interface ShareSavePayload {
+ isActive: boolean
+ authType?: ShareAuthType
+ password?: string
+ allowedEmails?: string[]
+ token?: string
+}
+
+export interface UseShareModalStateArgs {
+ resourceType: ShareResourceType
+ /** Authoritative server state; `null` while loading or when no share exists. */
+ saved: ShareRecord | null
+ /** True once the share query has settled — gates the pre-reserved-token link. */
+ isFetched: boolean
+ /** Org policy read from `usePermissionConfig`. `null` allowedAuthTypes = all allowed. */
+ policy: { disablePublicSharing: boolean; allowedAuthTypes: ShareAuthType[] | null }
+}
+
+export interface UseShareModalStateResult {
+ mode: ShareAccessMode
+ setMode: (mode: ShareAccessMode) => void
+ /** Modes to render in the ButtonGroup — filtered by policy, plus the saved mode. */
+ availableModes: ShareAccessMode[]
+ password: string
+ setPassword: (value: string) => void
+ emails: string[]
+ /** Replaces the whole allow-list; the emails control owns format validation and dedupe. */
+ setEmails: (next: string[]) => void
+ /** `null` until a link can honestly be shown (existing share, or a settled empty fetch). */
+ shareUrl: string | null
+ isDirty: boolean
+ passwordMissing: boolean
+ emailsMissing: boolean
+ modeDisallowed: boolean
+ enableBlockedByPolicy: boolean
+ canSave: boolean
+ buildSavePayload: () => ShareSavePayload
+ reset: () => void
+}
+
+/** Auth modes always offered; `sso` is appended only when the deployment enables it. */
+const BASE_AUTH_TYPES = ['public', 'password', 'email'] as const
+
+/** Stable identity so the emails control's reconcile effect no-ops while unset. */
+const EMPTY_EMAILS: string[] = []
+
+function toSavedMode(share: ShareRecord | null): ShareAccessMode {
+ if (!share?.isActive) return 'private'
+ return share.authType
+}
+
+/**
+ * The share dialog's state machine, without any chrome.
+ *
+ * Every share modal (files, interfaces) renders from this so the pre-reserved
+ * token, the null-until-touched drafts, the org-policy gates, and the save
+ * payload cannot drift between resources. Drafts stay `null` until the user
+ * touches a control, so each control keeps reflecting the authoritative saved
+ * state even when the share query resolves after mount.
+ *
+ * Callers mount the modal fresh on each open (a derived mount from a URL param),
+ * which is what reserves exactly one token per open.
+ */
+export function useShareModalState({
+ resourceType,
+ saved,
+ isFetched,
+ policy,
+}: UseShareModalStateArgs): UseShareModalStateResult {
+ /**
+ * Reserved on mount so the link can be shown and copied before the first
+ * save; persisted on save. Only surfaced once we've confirmed no share row
+ * exists yet, so a copied link always matches what gets stored.
+ */
+ const [pendingToken] = useState(() => generateShortId())
+
+ const [draftMode, setDraftMode] = useState(null)
+ const [password, setPassword] = useState('')
+ const [draftEmails, setDraftEmails] = useState(null)
+
+ const savedAccessMode = toSavedMode(saved)
+ const mode = draftMode ?? savedAccessMode
+ const isActive = mode !== 'private'
+ const emails = draftEmails ?? saved?.allowedEmails ?? EMPTY_EMAILS
+
+ const shareUrl = saved?.url ?? (isFetched ? buildShareUrl(resourceType, pendingToken) : null)
+
+ /**
+ * Org access-control may restrict which auth modes are allowed (`null` = all).
+ * The route is the source of truth; this just hides disallowed options.
+ */
+ const isAuthTypeAllowed = (candidate: ShareAuthType) =>
+ policy.allowedAuthTypes === null || policy.allowedAuthTypes.includes(candidate)
+
+ const ssoEnabled = isSsoEnabled || savedAccessMode === 'sso'
+ const candidateAuthTypes: ShareAuthType[] = [
+ ...BASE_AUTH_TYPES,
+ ...(ssoEnabled ? (['sso'] as const) : []),
+ ]
+ /** Keep the saved mode visible even if newly disallowed, so the current state shows. */
+ const availableModes: ShareAccessMode[] = [
+ 'private',
+ ...candidateAuthTypes.filter(
+ (candidate) => isAuthTypeAllowed(candidate) || candidate === savedAccessMode
+ ),
+ ]
+
+ /**
+ * The selected mode is blocked when org policy disables public sharing
+ * entirely (enabling a new share) or when the chosen auth mode isn't allowed.
+ */
+ const modeDisallowed = mode !== 'private' && !isAuthTypeAllowed(mode)
+ const enableBlockedByPolicy = (policy.disablePublicSharing && !saved?.isActive) || modeDisallowed
+
+ /** A password share needs a secret: either one already stored or a freshly typed one. */
+ const passwordMissing = mode === 'password' && !saved?.hasPassword && password.trim().length === 0
+ /** Email/SSO shares need at least one allowed email/domain. */
+ const emailsMissing = (mode === 'email' || mode === 'sso') && emails.length === 0
+
+ const emailsDirty =
+ draftEmails !== null &&
+ JSON.stringify(draftEmails) !== JSON.stringify(saved?.allowedEmails ?? [])
+ const isDirty =
+ (draftMode !== null && draftMode !== savedAccessMode) ||
+ (mode === 'password' && password.length > 0) ||
+ ((mode === 'email' || mode === 'sso') && emailsDirty)
+
+ const canSave =
+ isDirty && !passwordMissing && !emailsMissing && !(isActive && enableBlockedByPolicy)
+
+ const buildSavePayload = useCallback((): ShareSavePayload => {
+ /**
+ * Persist the reserved token only when creating the row; existing shares
+ * keep their own token (the server ignores this on conflict).
+ */
+ const token = saved ? undefined : pendingToken
+ if (mode === 'private') return { isActive: false, token }
+ if (mode === 'password') {
+ return {
+ isActive: true,
+ authType: 'password',
+ password: password.trim() || undefined,
+ token,
+ }
+ }
+ if (mode === 'email' || mode === 'sso') {
+ return { isActive: true, authType: mode, allowedEmails: emails, token }
+ }
+ return { isActive: true, authType: 'public', token }
+ }, [mode, password, emails, saved, pendingToken])
+
+ const reset = useCallback(() => {
+ setDraftMode(null)
+ setPassword('')
+ setDraftEmails(null)
+ }, [])
+
+ return {
+ mode,
+ setMode: setDraftMode,
+ availableModes,
+ password,
+ setPassword,
+ emails,
+ setEmails: setDraftEmails,
+ shareUrl,
+ isDirty,
+ passwordMissing,
+ emailsMissing,
+ modeDisallowed,
+ enableBlockedByPolicy,
+ canSave,
+ buildSavePayload,
+ reset,
+ }
+}
diff --git a/apps/sim/lib/api/contracts/chats.ts b/apps/sim/lib/api/contracts/chats.ts
index 2755536a5a2..06ba76027c7 100644
--- a/apps/sim/lib/api/contracts/chats.ts
+++ b/apps/sim/lib/api/contracts/chats.ts
@@ -133,6 +133,8 @@ export const deployedChatConfigSchema = z.object({
(value) => value ?? undefined,
z.array(deployedChatOutputConfigSchema).optional()
),
+ /** Display name of the deployer, for the header's "Shared by" credit. Omitted when unknown. */
+ sharedByName: z.string().min(1).optional(),
/** Policy for thinking SSE; clients still need the X-Sim-Stream-Protocol opt-in. */
includeThinking: z.preprocess((value) => value ?? false, z.boolean()),
/** Policy for tool lifecycle SSE; clients still need the protocol opt-in. */
diff --git a/apps/sim/lib/api/contracts/primitives.ts b/apps/sim/lib/api/contracts/primitives.ts
index f899a27174f..a860f4217ef 100644
--- a/apps/sim/lib/api/contracts/primitives.ts
+++ b/apps/sim/lib/api/contracts/primitives.ts
@@ -1,4 +1,4 @@
-import { isPlainRecord } from '@sim/utils/object'
+import { isPlainRecord, isRecordLike } from '@sim/utils/object'
import { z } from 'zod'
import { setRecordValue } from '@/lib/core/utils/records'
import { PII_LANGUAGE_CODES, stripNerEntities } from '@/lib/guardrails/pii-entities'
@@ -6,6 +6,20 @@ import { validateRegexPattern } from '@/lib/guardrails/validate_regex'
export const unknownRecordSchema = z.record(z.string(), z.unknown())
+/**
+ * Typed passthrough for a domain object whose shape the service layer already
+ * guarantees — validates only that the value is a plain record, keeping the
+ * response type precise without re-encoding the domain model as zod.
+ */
+export const domainObjectSchema = () => z.custom(isRecordLike)
+
+/** Canonical `{ success: true, data }` response envelope. */
+export const successResponseSchema = (dataSchema: T) =>
+ z.object({
+ success: z.literal(true),
+ data: dataSchema,
+ })
+
export const stringRecordSchema = z
.custom>(
(value) =>
diff --git a/apps/sim/lib/api/contracts/public-shares.ts b/apps/sim/lib/api/contracts/public-shares.ts
index a839d372ead..5464aa52491 100644
--- a/apps/sim/lib/api/contracts/public-shares.ts
+++ b/apps/sim/lib/api/contracts/public-shares.ts
@@ -2,8 +2,20 @@ import { z } from 'zod'
import { inlineFileRefQuerySchema, workspaceIdSchema } from '@/lib/api/contracts/primitives'
import { defineRouteContract } from '@/lib/api/contracts/types'
+/**
+ * What a `public_share` row points at. The DB column is free-form text and the
+ * composite unique index is `(resourceType, resourceId)`, so widening this enum
+ * is the designed extension point — no migration is involved.
+ */
export const shareResourceTypeSchema = z.enum(['file', 'folder'])
+/**
+ * Exported so server helpers (`share-manager`), client-safe helpers (`urls`),
+ * and query hooks can all name the same union instead of re-deriving it with
+ * `z.infer`, which clients are forbidden from writing.
+ */
+export type ShareResourceType = z.output
+
/** How a public share is gated. */
export const shareAuthTypeSchema = z.enum(['public', 'password', 'email', 'sso'])
diff --git a/apps/sim/lib/api/contracts/tables.ts b/apps/sim/lib/api/contracts/tables.ts
index 075a1a8a199..0b84215215f 100644
--- a/apps/sim/lib/api/contracts/tables.ts
+++ b/apps/sim/lib/api/contracts/tables.ts
@@ -1,8 +1,9 @@
-import { isRecordLike } from '@sim/utils/object'
import { z } from 'zod'
import {
+ domainObjectSchema,
folderIdSchema,
requiredFieldSchema,
+ successResponseSchema,
workspaceIdSchema,
} from '@/lib/api/contracts/primitives'
import { type ContractJsonResponse, defineRouteContract } from '@/lib/api/contracts/types'
@@ -34,8 +35,6 @@ import {
} from '@/lib/table/constants'
import { CSV_MAX_FILE_SIZE_BYTES } from '@/lib/table/import'
-export const domainObjectSchema = () => z.custom(isRecordLike)
-
/**
* Column types are a fixed enum derived from `COLUMN_TYPES` so callers cannot
* send arbitrary strings the server would reject downstream.
@@ -650,12 +649,6 @@ export const updateRowsByFilterBodySchema = z.object({
limit: optionalPositiveLimit(TABLE_LIMITS.MAX_BULK_OPERATION_SIZE, 'Limit').optional(),
})
-const successResponseSchema = (dataSchema: T) =>
- z.object({
- success: z.literal(true),
- data: dataSchema,
- })
-
const tableColumnsResponseDataSchema = z.object({
columns: z.array(tableColumnSchema),
})
diff --git a/apps/sim/lib/collab-doc/converter.test.ts b/apps/sim/lib/collab-doc/converter.test.ts
index ba5606600b6..b9602453368 100644
--- a/apps/sim/lib/collab-doc/converter.test.ts
+++ b/apps/sim/lib/collab-doc/converter.test.ts
@@ -7,8 +7,8 @@ import * as Y from 'yjs'
import {
applyFrontmatter,
postProcessSerializedMarkdown,
-} from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-fidelity'
-import { serializeMarkdownBody } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-parse'
+} from '@/components/resources/file-view/components/rich-markdown-editor/markdown-fidelity'
+import { serializeMarkdownBody } from '@/components/resources/file-view/components/rich-markdown-editor/markdown-parse'
import {
applyMarkdownToYDoc,
markdownToYDoc,
diff --git a/apps/sim/lib/collab-doc/converter.ts b/apps/sim/lib/collab-doc/converter.ts
index 990e0f906c6..4dae1fe4d88 100644
--- a/apps/sim/lib/collab-doc/converter.ts
+++ b/apps/sim/lib/collab-doc/converter.ts
@@ -8,15 +8,18 @@ import {
yDocToProsemirrorJSON,
} from '@tiptap/y-tiptap'
import type * as Y from 'yjs'
-import { createMarkdownContentExtensions } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/extensions'
+// boundary-resource-internal: server-side markdown schema/parsing only; the barrel would pull the React file view into the realtime persist path
+import { createMarkdownContentExtensions } from '@/components/resources/file-view/components/rich-markdown-editor/extensions'
+// boundary-resource-internal: server-side markdown schema/parsing only; the barrel would pull the React file view into the realtime persist path
import {
applyFrontmatter,
postProcessSerializedMarkdown,
-} from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-fidelity'
+} from '@/components/resources/file-view/components/rich-markdown-editor/markdown-fidelity'
+// boundary-resource-internal: server-side markdown schema/parsing only; the barrel would pull the React file view into the realtime persist path
import {
parseMarkdownToDoc,
serializeDocToMarkdown,
-} from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-parse'
+} from '@/components/resources/file-view/components/rich-markdown-editor/markdown-parse'
/**
* Server-side conversion between a file's markdown and its collaborative Yjs document.
diff --git a/apps/sim/lib/collab-doc/merge.test.ts b/apps/sim/lib/collab-doc/merge.test.ts
index bb4b28196c5..132a843d9c4 100644
--- a/apps/sim/lib/collab-doc/merge.test.ts
+++ b/apps/sim/lib/collab-doc/merge.test.ts
@@ -4,7 +4,7 @@
import { FILE_DOC_SEED } from '@sim/realtime-protocol/file-doc'
import { describe, expect, it } from 'vitest'
import * as Y from 'yjs'
-import { serializeMarkdownBody } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-parse'
+import { serializeMarkdownBody } from '@/components/resources/file-view/components/rich-markdown-editor/markdown-parse'
import { markdownToYDoc, yDocToMarkdown } from './converter'
import { buildFileDocMergeUpdate } from './merge'
diff --git a/apps/sim/lib/collab-doc/merge.ts b/apps/sim/lib/collab-doc/merge.ts
index 85e5bee9733..1b329ddd566 100644
--- a/apps/sim/lib/collab-doc/merge.ts
+++ b/apps/sim/lib/collab-doc/merge.ts
@@ -1,6 +1,7 @@
import { FILE_DOC_SEED } from '@sim/realtime-protocol/file-doc'
import * as Y from 'yjs'
-import { splitFrontmatter } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-fidelity'
+// boundary-resource-internal: server-side markdown fidelity only; the barrel would pull the React file view into the realtime persist path
+import { splitFrontmatter } from '@/components/resources/file-view/components/rich-markdown-editor/markdown-fidelity'
import { applyMarkdownToYDoc } from './converter'
/**
diff --git a/apps/sim/lib/collab-doc/seed.test.ts b/apps/sim/lib/collab-doc/seed.test.ts
index 28e8562464a..321ce204731 100644
--- a/apps/sim/lib/collab-doc/seed.test.ts
+++ b/apps/sim/lib/collab-doc/seed.test.ts
@@ -23,7 +23,7 @@ vi.mock('./collab-state', () => ({
loadFreshCollabDocState: mockLoadFresh,
}))
-import { serializeMarkdownBody } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-parse'
+import { serializeMarkdownBody } from '@/components/resources/file-view/components/rich-markdown-editor/markdown-parse'
import { yDocToMarkdown } from './converter'
import { buildFileDocSeed } from './seed'
diff --git a/apps/sim/lib/collab-doc/seed.ts b/apps/sim/lib/collab-doc/seed.ts
index ece65549bf0..180169397e2 100644
--- a/apps/sim/lib/collab-doc/seed.ts
+++ b/apps/sim/lib/collab-doc/seed.ts
@@ -2,8 +2,9 @@ import { createLogger } from '@sim/logger'
import { FILE_DOC_SEED } from '@sim/realtime-protocol/file-doc'
import { getErrorMessage } from '@sim/utils/errors'
import * as Y from 'yjs'
+// boundary-resource-internal: server-side markdown fidelity only; the barrel would pull the React file view into the realtime persist path
+import { splitFrontmatter } from '@/components/resources/file-view/components/rich-markdown-editor/markdown-fidelity'
import { fetchWorkspaceFileBuffer, getWorkspaceFile } from '@/lib/uploads/contexts/workspace'
-import { splitFrontmatter } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-fidelity'
import { hashMarkdown, loadFreshCollabDocState } from './collab-state'
import { markdownToYDoc } from './converter'
diff --git a/apps/sim/lib/compare/data/sim.ts b/apps/sim/lib/compare/data/sim.ts
index b2a46f0b893..6cbd81d6a1e 100644
--- a/apps/sim/lib/compare/data/sim.ts
+++ b/apps/sim/lib/compare/data/sim.ts
@@ -275,7 +275,7 @@ export const simProfile: CompetitorProfile = {
confidence: 'verified',
sources: [
{
- url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/app/workspace/%5BworkspaceId%5D/files/components/share-modal/share-modal.tsx',
+ url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/app/workspace/%5BworkspaceId%5D/components/share-modal/share-modal.tsx',
label: 'Sim codebase: file share modal (password/email/SSO modes)',
asOf: '2026-07-08',
},
@@ -308,7 +308,7 @@ export const simProfile: CompetitorProfile = {
confidence: 'verified',
sources: [
{
- url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx',
+ url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/components/resources/file-view/components/rich-markdown-editor/rich-markdown-editor.tsx',
label: 'Sim codebase: rich markdown editor',
asOf: '2026-07-02',
},
diff --git a/apps/sim/lib/copilot/resources/types.ts b/apps/sim/lib/copilot/resources/types.ts
index 6e78ddd5ebd..0fa482ffb59 100644
--- a/apps/sim/lib/copilot/resources/types.ts
+++ b/apps/sim/lib/copilot/resources/types.ts
@@ -141,6 +141,7 @@ export function canonicalizeDesktopSessionResources(
/** Placeholder resource titles that a more specific title may overwrite during dedup. */
export const GENERIC_RESOURCE_TITLES = new Set([
'Table',
+ 'Interface',
'File',
'Workflow',
'Knowledge Base',
diff --git a/apps/sim/lib/copilot/tools/handlers/resources.test.ts b/apps/sim/lib/copilot/tools/handlers/resources.test.ts
index 8e69e1dce8f..c27fbd737cd 100644
--- a/apps/sim/lib/copilot/tools/handlers/resources.test.ts
+++ b/apps/sim/lib/copilot/tools/handlers/resources.test.ts
@@ -97,4 +97,63 @@ describe('executeOpenResource', () => {
],
})
})
+
+ it('opens workflow alias file paths through workspace file reference resolution', async () => {
+ resolveWorkspaceFileReferenceMock.mockResolvedValue({
+ id: 'wf_plan_file',
+ name: 'implementation.md',
+ folderPath: 'system/workflows/My Workflow/.plans',
+ })
+
+ const result = await executeOpenResource(
+ {
+ resources: [{ type: 'file', path: 'workflows/My%20Workflow/.plans/implementation.md' }],
+ },
+ { userId: 'user-1', workflowId: 'workflow-1', workspaceId: 'workspace-1' }
+ )
+
+ expect(resolveWorkspaceFileReferenceMock).toHaveBeenCalledWith(
+ 'workspace-1',
+ 'workflows/My%20Workflow/.plans/implementation.md'
+ )
+ expect(result).toMatchObject({
+ success: true,
+ resources: [
+ {
+ type: 'file',
+ id: 'wf_plan_file',
+ title: 'implementation.md',
+ path: 'files/system/workflows/My%20Workflow/.plans/implementation.md',
+ },
+ ],
+ })
+ })
+
+ it('opens root plan alias file paths through workspace file reference resolution', async () => {
+ resolveWorkspaceFileReferenceMock.mockResolvedValue({
+ id: 'wf_root_plan',
+ name: 'root.md',
+ folderPath: 'system/.plans',
+ })
+
+ const result = await executeOpenResource(
+ {
+ resources: [{ type: 'file', path: '.plans/root.md' }],
+ },
+ { userId: 'user-1', workflowId: 'workflow-1', workspaceId: 'workspace-1' }
+ )
+
+ expect(resolveWorkspaceFileReferenceMock).toHaveBeenCalledWith('workspace-1', '.plans/root.md')
+ expect(result).toMatchObject({
+ success: true,
+ resources: [
+ {
+ type: 'file',
+ id: 'wf_root_plan',
+ title: 'root.md',
+ path: 'files/system/.plans/root.md',
+ },
+ ],
+ })
+ })
})
diff --git a/apps/sim/lib/copilot/tools/server/base-tool.ts b/apps/sim/lib/copilot/tools/server/base-tool.ts
index cf0a91cee93..e269f5d11be 100644
--- a/apps/sim/lib/copilot/tools/server/base-tool.ts
+++ b/apps/sim/lib/copilot/tools/server/base-tool.ts
@@ -1,6 +1,27 @@
+import { toError } from '@sim/utils/errors'
import type { z } from 'zod'
import type { BillingAttributionSnapshot } from '@/lib/billing/core/billing-attribution'
+/**
+ * Normalizes an unexpected tool failure for logging and for the model:
+ * `errorMessage`/`cause` feed the tool's structured `logger.error`, and
+ * `displayMessage` (message with its `cause` appended when present) goes into
+ * the `Operation failed:` envelope returned to the model.
+ */
+export function formatServerToolError(error: unknown): {
+ errorMessage: string
+ cause?: string
+ displayMessage: string
+} {
+ const errorMessage = toError(error).message
+ const cause = error instanceof Error && error.cause ? toError(error.cause).message : undefined
+ return {
+ errorMessage,
+ cause,
+ displayMessage: cause ? `${errorMessage} (${cause})` : errorMessage,
+ }
+}
+
export interface ServerToolContext {
userId: string
workspaceId?: string
diff --git a/apps/sim/lib/copilot/tools/server/files/share-file.ts b/apps/sim/lib/copilot/tools/server/files/share-file.ts
index 6a3dc36ee36..18503947548 100644
--- a/apps/sim/lib/copilot/tools/server/files/share-file.ts
+++ b/apps/sim/lib/copilot/tools/server/files/share-file.ts
@@ -11,7 +11,7 @@ import {
import {
getShareForResource,
ShareValidationError,
- upsertFileShare,
+ upsertResourceShare,
} from '@/lib/public-shares/share-manager'
import {
getWorkspaceFile,
@@ -96,7 +96,7 @@ export const shareFileServerTool: BaseServerTool
// master on/off and the per-auth-type allow-list); disabling is always
// allowed so users can still un-share after the policy is turned on.
if (isActive) {
- // Validate the auth type that will ACTUALLY be persisted. upsertFileShare
+ // Validate the auth type that will ACTUALLY be persisted. upsertResourceShare
// falls back to the existing share's authType when none is passed, so a bare
// re-enable must be checked against that stored mode — not 'public' — or a
// now-disallowed password/email/sso share could be silently reactivated.
@@ -115,9 +115,10 @@ export const shareFileServerTool: BaseServerTool
let share
try {
- share = await upsertFileShare({
+ share = await upsertResourceShare({
+ resourceType: 'file',
+ resourceId: fileId,
workspaceId,
- fileId,
userId: context.userId,
isActive,
authType,
diff --git a/apps/sim/lib/copilot/tools/server/table/user-table.ts b/apps/sim/lib/copilot/tools/server/table/user-table.ts
index dd81326fefc..5b996542dc1 100644
--- a/apps/sim/lib/copilot/tools/server/table/user-table.ts
+++ b/apps/sim/lib/copilot/tools/server/table/user-table.ts
@@ -6,6 +6,7 @@ import { UserTable } from '@/lib/copilot/generated/tool-catalog-v1'
import {
assertServerToolNotAborted,
type BaseServerTool,
+ formatServerToolError,
type ServerToolContext,
} from '@/lib/copilot/tools/server/base-tool'
import { isTriggerDevEnabled } from '@/lib/core/config/env-flags'
@@ -2344,14 +2345,12 @@ export const userTableServerTool: BaseServerTool
return { success: false, message: `Unknown operation: ${operation}` }
}
} catch (error) {
- const errorMessage = toError(error).message
- const cause = error instanceof Error && error.cause ? toError(error.cause).message : undefined
+ const { errorMessage, cause, displayMessage } = formatServerToolError(error)
logger.error('Table operation failed', {
operation,
error: errorMessage,
cause,
})
- const displayMessage = cause ? `${errorMessage} (${cause})` : errorMessage
return { success: false, message: `Operation failed: ${displayMessage}` }
}
},
diff --git a/apps/sim/lib/copilot/tools/tool-display.ts b/apps/sim/lib/copilot/tools/tool-display.ts
index c8623c9b237..4307e04417d 100644
--- a/apps/sim/lib/copilot/tools/tool-display.ts
+++ b/apps/sim/lib/copilot/tools/tool-display.ts
@@ -498,6 +498,7 @@ const TOOL_TITLES: Record = {
auth: 'Auth Agent',
knowledge: 'Knowledge Agent',
table: 'Table Agent',
+ interface: 'Interface Agent',
agent: 'Tools Agent',
research: 'Research Agent',
scout: 'Scout Agent',
@@ -977,6 +978,7 @@ const COMPLETED_VERB_REWRITES: Record = {
Querying: 'Queried',
Reading: 'Read',
Redeploying: 'Redeployed',
+ Removing: 'Removed',
Renaming: 'Renamed',
Requesting: 'Requested',
Resizing: 'Resized',
diff --git a/apps/sim/lib/copilot/vfs/path-utils.test.ts b/apps/sim/lib/copilot/vfs/path-utils.test.ts
index b2df921be1a..ada2a910109 100644
--- a/apps/sim/lib/copilot/vfs/path-utils.test.ts
+++ b/apps/sim/lib/copilot/vfs/path-utils.test.ts
@@ -5,6 +5,7 @@ import { describe, expect, it } from 'vitest'
import {
buildVfsFolderPathMap,
canonicalBlockVfsPath,
+ canonicalInterfaceVfsPath,
canonicalKnowledgeBaseVfsDir,
canonicalTableVfsPath,
canonicalWorkflowVfsDir,
@@ -50,8 +51,9 @@ describe('canonical resource VFS paths', () => {
).toBe('workflows/My%20Folder/Sub%20Folder/My%20Flow')
})
- it('builds table, knowledge base, and block pointers', () => {
+ it('builds table, interface, knowledge base, and block pointers', () => {
expect(canonicalTableVfsPath('Sales Data')).toBe('tables/Sales%20Data/meta.json')
+ expect(canonicalInterfaceVfsPath('Support Desk')).toBe('interfaces/Support%20Desk/meta.json')
expect(canonicalKnowledgeBaseVfsDir('Docs — KB')).toBe('knowledgebases/Docs%20%E2%80%94%20KB')
expect(canonicalBlockVfsPath('agent')).toBe('components/blocks/agent.json')
})
diff --git a/apps/sim/lib/copilot/vfs/path-utils.ts b/apps/sim/lib/copilot/vfs/path-utils.ts
index daeb5c0a631..5cae8e92489 100644
--- a/apps/sim/lib/copilot/vfs/path-utils.ts
+++ b/apps/sim/lib/copilot/vfs/path-utils.ts
@@ -126,6 +126,11 @@ export function canonicalTableVfsPath(name: string): string {
return `tables/${encodeVfsSegment(name)}/meta.json`
}
+/** Canonical VFS path for an interface's metadata file (`interfaces/{name}/meta.json`). */
+export function canonicalInterfaceVfsPath(name: string): string {
+ return `interfaces/${encodeVfsSegment(name)}/meta.json`
+}
+
/** Canonical VFS directory for a knowledge base (`knowledgebases/{name}`). */
export function canonicalKnowledgeBaseVfsDir(name: string): string {
return `knowledgebases/${encodeVfsSegment(name)}`
diff --git a/apps/sim/lib/core/security/otp.ts b/apps/sim/lib/core/security/otp.ts
index 326a48cec8a..810a023c1d0 100644
--- a/apps/sim/lib/core/security/otp.ts
+++ b/apps/sim/lib/core/security/otp.ts
@@ -10,7 +10,8 @@ import { getStorageMethod } from '@/lib/core/storage'
export type DeploymentKind = 'chat' | 'file'
/**
- * Shared OTP configuration for deployment email-auth gates (chat + public file shares).
+ * Shared OTP configuration for deployment email-auth gates (chat + public file
+ * and interface shares).
*/
export const OTP_EXPIRY_SECONDS = 15 * 60
export const OTP_EXPIRY_MS = OTP_EXPIRY_SECONDS * 1000
diff --git a/apps/sim/lib/core/utils/response-format.ts b/apps/sim/lib/core/utils/response-format.ts
index 97a57d0e72c..6da3129b996 100644
--- a/apps/sim/lib/core/utils/response-format.ts
+++ b/apps/sim/lib/core/utils/response-format.ts
@@ -128,6 +128,27 @@ export function formatFieldValues(extractedValues: Record): string
return formattedValues.join('\n')
}
+/**
+ * Serializes one output config onto the `selectedOutputs` wire format that
+ * `extractBlockIdFromOutputId`/`extractPathFromOutputId` decode —
+ * `${blockId}_${path}`, where an empty path means the block's `content` field.
+ */
+export function serializeOutputId(config: { blockId: string; path?: string | null }): string {
+ return config.path ? `${config.blockId}_${config.path}` : `${config.blockId}_content`
+}
+
+/**
+ * Serializes a list of output configs onto the `selectedOutputs` wire, in
+ * config order. The single source of the format — every producer (deployed
+ * chat, interface chat, module pickers) must go through this rather than
+ * hand-rolling the template.
+ */
+export function serializeSelectedOutputs(
+ outputConfigs: readonly { blockId: string; path?: string | null }[]
+): string[] {
+ return outputConfigs.map(serializeOutputId)
+}
+
/**
* Extract block ID from output ID
* Handles both formats: "blockId" and "blockId_path" or "blockId.path"
diff --git a/apps/sim/lib/core/utils/restore-name.ts b/apps/sim/lib/core/utils/restore-name.ts
index 352cfde22cb..2f682c015f9 100644
--- a/apps/sim/lib/core/utils/restore-name.ts
+++ b/apps/sim/lib/core/utils/restore-name.ts
@@ -1,7 +1,46 @@
import { randomBytes } from 'crypto'
+import { getPostgresErrorCode } from '@sim/utils/errors'
const HASH_ATTEMPTS = 8
+const UNIQUE_VIOLATION_RETRIES = 8
+
+/**
+ * Retry harness for a restore-rename write: runs `attempt` — one full try at
+ * choosing a restore name (via {@link generateRestoreName}) and persisting the
+ * restore — retrying on Postgres unique violations (23505). A concurrent
+ * create/rename can claim the chosen name between the availability check and
+ * commit (MVCC), so each retry re-picks a fresh suffix.
+ *
+ * `attempt` reports the name it is about to claim through its
+ * `reportAttemptedName` argument; after exhausting retries that name (or
+ * `originalName` when none was reported) is passed to `makeConflictError` and
+ * the result thrown. Non-23505 errors propagate unchanged.
+ */
+export async function restoreWithUniqueName(
+ originalName: string,
+ makeConflictError: (attemptedName: string) => Error,
+ attempt: (reportAttemptedName: (name: string) => void) => Promise
+): Promise {
+ let attemptedName = ''
+ for (let i = 0; i < UNIQUE_VIOLATION_RETRIES; i++) {
+ attemptedName = ''
+ try {
+ return await attempt((name) => {
+ attemptedName = name
+ })
+ } catch (error: unknown) {
+ if (getPostgresErrorCode(error) !== '23505') {
+ throw error
+ }
+ if (i === UNIQUE_VIOLATION_RETRIES - 1) {
+ throw makeConflictError(attemptedName || originalName)
+ }
+ }
+ }
+ throw makeConflictError(originalName)
+}
+
/**
* Generates a unique name for a restored entity by trying in order:
* 1. The original name
diff --git a/apps/sim/lib/core/utils/unique-name.test.ts b/apps/sim/lib/core/utils/unique-name.test.ts
new file mode 100644
index 00000000000..f83f99a4575
--- /dev/null
+++ b/apps/sim/lib/core/utils/unique-name.test.ts
@@ -0,0 +1,41 @@
+/**
+ * @vitest-environment node
+ */
+import { describe, expect, it } from 'vitest'
+import { generateUniqueName } from '@/lib/core/utils/unique-name'
+
+const simpleFormat = (attempt: number) => (attempt === 0 ? 'File' : `File ${attempt + 1}`)
+const fileFormat = (attempt: number) => (attempt === 0 ? 'untitled.md' : `untitled (${attempt}).md`)
+
+describe('generateUniqueName', () => {
+ it('returns the base name when nothing is taken', () => {
+ expect(generateUniqueName([], simpleFormat)).toBe('File')
+ })
+
+ it('increments the suffix until a free name is found', () => {
+ expect(generateUniqueName(['untitled.md', 'untitled (1).md'], fileFormat)).toBe(
+ 'untitled (2).md'
+ )
+ })
+
+ it('skips gaps left by deleted names', () => {
+ expect(generateUniqueName(['untitled.md', 'untitled (2).md'], fileFormat)).toBe(
+ 'untitled (1).md'
+ )
+ })
+
+ it('compares case-sensitively by default', () => {
+ expect(generateUniqueName(['FILE'], simpleFormat)).toBe('File')
+ })
+
+ it('compares case-insensitively when requested', () => {
+ expect(generateUniqueName(['FILE'], simpleFormat, { caseInsensitive: true })).toBe('File 2')
+ expect(generateUniqueName(['file', 'File 2'], simpleFormat, { caseInsensitive: true })).toBe(
+ 'File 3'
+ )
+ })
+
+ it('accepts any iterable of existing names', () => {
+ expect(generateUniqueName(new Set(['untitled.md']), fileFormat)).toBe('untitled (1).md')
+ })
+})
diff --git a/apps/sim/lib/core/utils/unique-name.ts b/apps/sim/lib/core/utils/unique-name.ts
new file mode 100644
index 00000000000..3ff40d0baaf
--- /dev/null
+++ b/apps/sim/lib/core/utils/unique-name.ts
@@ -0,0 +1,29 @@
+/**
+ * First name from `formatCandidate(0)`, `formatCandidate(1)`, … that is not in
+ * `existingNames`. By convention `formatCandidate(0)` is the base name and
+ * higher attempts produce suffixed variants (e.g. `` (n) => n === 0 ? 'New
+ * folder' : `New folder (${n})` ``). Terminates within `existingNames.length
+ * + 1` iterations since each attempt yields a distinct candidate.
+ *
+ * @param existingNames - Names already taken.
+ * @param formatCandidate - Builds the candidate for a given attempt number.
+ * @param options - Set `caseInsensitive` to compare names case-insensitively.
+ */
+export function generateUniqueName(
+ existingNames: Iterable,
+ formatCandidate: (attempt: number) => string,
+ options?: { caseInsensitive?: boolean }
+): string {
+ const caseInsensitive = options?.caseInsensitive ?? false
+ const normalize = (name: string) => (caseInsensitive ? name.toLowerCase() : name)
+
+ const taken = new Set()
+ for (const name of existingNames) {
+ taken.add(normalize(name))
+ }
+
+ for (let attempt = 0; ; attempt++) {
+ const candidate = formatCandidate(attempt)
+ if (!taken.has(normalize(candidate))) return candidate
+ }
+}
diff --git a/apps/sim/lib/execution/sandbox/bundles/pptxgenjs.cjs b/apps/sim/lib/execution/sandbox/bundles/pptxgenjs.cjs
index 2de5cfcc238..8afcca8bca5 100644
--- a/apps/sim/lib/execution/sandbox/bundles/pptxgenjs.cjs
+++ b/apps/sim/lib/execution/sandbox/bundles/pptxgenjs.cjs
@@ -1,9 +1,9 @@
// sandbox bundle: pptxgenjs
// generated by apps/sim/lib/execution/sandbox/bundles/build.ts
// do not edit by hand. run `bun run build:sandbox-bundles` to regenerate.
-(()=>{var fJ=Object.create;var{getPrototypeOf:RJ,defineProperty:X6,getOwnPropertyNames:$9,getOwnPropertyDescriptor:IJ}=Object,Q9=Object.prototype.hasOwnProperty;function q9($){return this[$]}var CJ,jJ,K9=($,q,Q)=>{var K=$!=null&&typeof $==="object";if(K){var J=q?CJ??=new WeakMap:jJ??=new WeakMap,Z=J.get($);if(Z)return Z}Q=$!=null?fJ(RJ($)):{};let G=q||!$||!$.__esModule?X6(Q,"default",{value:$,enumerable:!0}):Q;for(let W of $9($))if(!Q9.call(G,W))X6(G,W,{get:q9.bind($,W),enumerable:!0});if(K)J.set($,G);return G},X0=($)=>{var q=(e7??=new WeakMap).get($),Q;if(q)return q;if(q=X6({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function"){for(var K of $9($))if(!Q9.call(q,K))X6(q,K,{get:q9.bind($,K),enumerable:!(Q=IJ($,K))||Q.enumerable})}return e7.set($,q),q},e7,N0=($,q)=>()=>(q||$((q={exports:{}}).exports,q),q.exports);var gJ=($)=>$;function AJ($,q){this[$]=gJ.bind(null,q)}var c1=($,q)=>{for(var Q in q)X6($,Q,{get:q[Q],enumerable:!0,configurable:!0,set:AJ.bind(q,Q)})};var b1=($,q)=>()=>($&&(q=$($=0)),q);var J9=(($)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy($,{get:(q,Q)=>(typeof require<"u"?require:q)[Q]}):$)(function($){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+$+'" is not supported')});var K2={};c1(K2,{transcode:()=>MV,resolveObjectURL:()=>BV,kStringMaxLength:()=>w9,kMaxLength:()=>y6,isUtf8:()=>zV,isAscii:()=>FV,default:()=>wV,constants:()=>EJ,btoa:()=>PJ,atob:()=>TJ,INSPECT_MAX_BYTES:()=>M9,File:()=>uJ,Buffer:()=>o,Blob:()=>SJ});function XJ($){var q=$.length;if(q%4>0)throw Error("Invalid string. Length must be a multiple of 4");var Q=$.indexOf("=");if(Q===-1)Q=q;var K=Q===q?0:4-Q%4;return[Q,K]}function yJ($,q){return($+q)*3/4-q}function hJ($){var q,Q=XJ($),K=Q[0],J=Q[1],Z=new Uint8Array(yJ(K,J)),G=0,W=J>0?K-4:K,B;for(B=0;B>16&255,Z[G++]=q>>8&255,Z[G++]=q&255;if(J===2)q=F2[$.charCodeAt(B)]<<2|F2[$.charCodeAt(B+1)]>>4,Z[G++]=q&255;if(J===1)q=F2[$.charCodeAt(B)]<<10|F2[$.charCodeAt(B+1)]<<4|F2[$.charCodeAt(B+2)]>>2,Z[G++]=q>>8&255,Z[G++]=q&255;return Z}function xJ($){return I2[$>>18&63]+I2[$>>12&63]+I2[$>>6&63]+I2[$&63]}function OJ($,q,Q){var K,J=[];for(var Z=q;ZW?W:G+Z));if(K===1)q=$[Q-1],J.push(I2[q>>2]+I2[q<<4&63]+"==");else if(K===2)q=($[Q-2]<<8)+$[Q-1],J.push(I2[q>>10]+I2[q>>4&63]+I2[q<<2&63]+"=");return J.join("")}function N8($,q,Q,K,J){var Z,G,W=J*8-K-1,B=(1<>1,U=-7,w=Q?J-1:0,F=Q?-1:1,M=$[q+w];w+=F,Z=M&(1<<-U)-1,M>>=-U,U+=W;for(;U>0;Z=Z*256+$[q+w],w+=F,U-=8);G=Z&(1<<-U)-1,Z>>=-U,U+=K;for(;U>0;G=G*256+$[q+w],w+=F,U-=8);if(Z===0)Z=1-V;else if(Z===B)return G?NaN:(M?-1:1)*(1/0);else G=G+Math.pow(2,K),Z=Z-V;return(M?-1:1)*G*Math.pow(2,Z-K)}function F9($,q,Q,K,J,Z){var G,W,B,V=Z*8-J-1,U=(1<>1,F=J===23?Math.pow(2,-24)-Math.pow(2,-77):0,M=K?0:Z-1,k=K?1:-1,f=q<0||q===0&&1/q<0?1:0;if(q=Math.abs(q),isNaN(q)||q===1/0)W=isNaN(q)?1:0,G=U;else{if(G=Math.floor(Math.log(q)/Math.LN2),q*(B=Math.pow(2,-G))<1)G--,B*=2;if(G+w>=1)q+=F/B;else q+=F*Math.pow(2,1-w);if(q*B>=2)G++,B/=2;if(G+w>=U)W=0,G=U;else if(G+w>=1)W=(q*B-1)*Math.pow(2,J),G=G+w;else W=q*Math.pow(2,w-1)*Math.pow(2,J),G=0}for(;J>=8;$[Q+M]=W&255,M+=k,W/=256,J-=8);G=G<0;$[Q+M]=G&255,M+=k,G/=256,V-=8);$[Q+M-k]|=f*128}function S2($){if($>y6)throw RangeError('The value "'+$+'" is invalid for option "size"');let q=new Uint8Array($);return Object.setPrototypeOf(q,o.prototype),q}function h5($,q,Q){return class extends Q{constructor(){super();Object.defineProperty(this,"message",{value:q.apply(this,arguments),writable:!0,configurable:!0}),this.name=`${this.name} [${$}]`,this.stack,delete this.name}get code(){return $}set code(K){Object.defineProperty(this,"code",{configurable:!0,enumerable:!0,value:K,writable:!0})}toString(){return`${this.name} [${$}]: ${this.message}`}}}function o($,q,Q){if(typeof $==="number"){if(typeof q==="string")throw TypeError('The "string" argument must be of type string. Received type number');return x5($)}return N9($,q,Q)}function N9($,q,Q){if(typeof $==="string")return nJ($,q);if(ArrayBuffer.isView($))return dJ($);if($==null)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof $);if(C2($,ArrayBuffer)||$&&C2($.buffer,ArrayBuffer))return X5($,q,Q);if(typeof SharedArrayBuffer<"u"&&(C2($,SharedArrayBuffer)||$&&C2($.buffer,SharedArrayBuffer)))return X5($,q,Q);if(typeof $==="number")throw TypeError('The "value" argument must not be of type number. Received type number');let K=$.valueOf&&$.valueOf();if(K!=null&&K!==$)return o.from(K,q,Q);let J=mJ($);if(J)return J;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof $[Symbol.toPrimitive]==="function")return o.from($[Symbol.toPrimitive]("string"),q,Q);throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof $)}function Y9($){if(typeof $!=="number")throw TypeError('"size" argument must be of type number');else if($<0)throw RangeError('The value "'+$+'" is invalid for option "size"')}function bJ($,q,Q){if(Y9($),$<=0)return S2($);if(q!==void 0)return typeof Q==="string"?S2($).fill(q,Q):S2($).fill(q);return S2($)}function x5($){return Y9($),S2($<0?0:O5($)|0)}function nJ($,q){if(typeof q!=="string"||q==="")q="utf8";if(!o.isEncoding(q))throw TypeError("Unknown encoding: "+q);let Q=k9($,q)|0,K=S2(Q),J=K.write($,q);if(J!==Q)K=K.slice(0,J);return K}function A5($){let q=$.length<0?0:O5($.length)|0,Q=S2(q);for(let K=0;K=y6)throw RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+y6.toString(16)+" bytes");return $|0}function k9($,q){if(o.isBuffer($))return $.length;if(ArrayBuffer.isView($)||C2($,ArrayBuffer))return $.byteLength;if(typeof $!=="string")throw TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof $);let Q=$.length,K=arguments.length>2&&arguments[2]===!0;if(!K&&Q===0)return 0;let J=!1;for(;;)switch(q){case"ascii":case"latin1":case"binary":return Q;case"utf8":case"utf-8":return y5($).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Q*2;case"hex":return Q>>>1;case"base64":return j9($).length;default:if(J)return K?-1:y5($).length;q=(""+q).toLowerCase(),J=!0}}function pJ($,q,Q){let K=!1;if(q===void 0||q<0)q=0;if(q>this.length)return"";if(Q===void 0||Q>this.length)Q=this.length;if(Q<=0)return"";if(Q>>>=0,q>>>=0,Q<=q)return"";if(!$)$="utf8";while(!0)switch($){case"hex":return QV(this,q,Q);case"utf8":case"utf-8":return L9(this,q,Q);case"ascii":return eJ(this,q,Q);case"latin1":case"binary":return $V(this,q,Q);case"base64":return sJ(this,q,Q);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return qV(this,q,Q);default:if(K)throw TypeError("Unknown encoding: "+$);$=($+"").toLowerCase(),K=!0}}function w1($,q,Q){let K=$[q];$[q]=$[Q],$[Q]=K}function D9($,q,Q,K,J){if($.length===0)return-1;if(typeof Q==="string")K=Q,Q=0;else if(Q>2147483647)Q=2147483647;else if(Q<-2147483648)Q=-2147483648;if(Q=+Q,Number.isNaN(Q))Q=J?0:$.length-1;if(Q<0)Q=$.length+Q;if(Q>=$.length)if(J)return-1;else Q=$.length-1;else if(Q<0)if(J)Q=0;else return-1;if(typeof q==="string")q=o.from(q,K);if(o.isBuffer(q)){if(q.length===0)return-1;return W9($,q,Q,K,J)}else if(typeof q==="number"){if(q=q&255,typeof Uint8Array.prototype.indexOf==="function")if(J)return Uint8Array.prototype.indexOf.call($,q,Q);else return Uint8Array.prototype.lastIndexOf.call($,q,Q);return W9($,[q],Q,K,J)}throw TypeError("val must be string, number or Buffer")}function W9($,q,Q,K,J){let Z=1,G=$.length,W=q.length;if(K!==void 0){if(K=String(K).toLowerCase(),K==="ucs2"||K==="ucs-2"||K==="utf16le"||K==="utf-16le"){if($.length<2||q.length<2)return-1;Z=2,G/=2,W/=2,Q/=2}}function B(U,w){if(Z===1)return U[w];else return U.readUInt16BE(w*Z)}let V;if(J){let U=-1;for(V=Q;VG)Q=G-W;for(V=Q;V>=0;V--){let U=!0;for(let w=0;wJ)K=J;let Z=q.length;if(K>Z/2)K=Z/2;let G;for(G=0;G239?4:Z>223?3:Z>191?2:1;if(J+W<=Q){let B,V,U,w;switch(W){case 1:if(Z<128)G=Z;break;case 2:if(B=$[J+1],(B&192)===128){if(w=(Z&31)<<6|B&63,w>127)G=w}break;case 3:if(B=$[J+1],V=$[J+2],(B&192)===128&&(V&192)===128){if(w=(Z&15)<<12|(B&63)<<6|V&63,w>2047&&(w<55296||w>57343))G=w}break;case 4:if(B=$[J+1],V=$[J+2],U=$[J+3],(B&192)===128&&(V&192)===128&&(U&192)===128){if(w=(Z&15)<<18|(B&63)<<12|(V&63)<<6|U&63,w>65535&&w<1114112)G=w}}}if(G===null)G=65533,W=1;else if(G>65535)G-=65536,K.push(G>>>10&1023|55296),G=56320|G&1023;K.push(G),J+=W}return tJ(K)}function tJ($){let q=$.length;if(q<=B9)return String.fromCharCode.apply(String,$);let Q="",K=0;while(KK)Q=K;let J="";for(let Z=q;ZQ)throw RangeError("Trying to access beyond buffer length")}function s0($,q,Q,K,J,Z){if(!o.isBuffer($))throw TypeError('"buffer" argument must be a Buffer instance');if(q>J||q$.length)throw RangeError("Index out of range")}function H9($,q,Q,K,J){C9(q,K,J,$,Q,7);let Z=Number(q&BigInt(4294967295));$[Q++]=Z,Z=Z>>8,$[Q++]=Z,Z=Z>>8,$[Q++]=Z,Z=Z>>8,$[Q++]=Z;let G=Number(q>>BigInt(32)&BigInt(4294967295));return $[Q++]=G,G=G>>8,$[Q++]=G,G=G>>8,$[Q++]=G,G=G>>8,$[Q++]=G,Q}function v9($,q,Q,K,J){C9(q,K,J,$,Q,7);let Z=Number(q&BigInt(4294967295));$[Q+7]=Z,Z=Z>>8,$[Q+6]=Z,Z=Z>>8,$[Q+5]=Z,Z=Z>>8,$[Q+4]=Z;let G=Number(q>>BigInt(32)&BigInt(4294967295));return $[Q+3]=G,G=G>>8,$[Q+2]=G,G=G>>8,$[Q+1]=G,G=G>>8,$[Q]=G,Q+8}function f9($,q,Q,K,J,Z){if(Q+K>$.length)throw RangeError("Index out of range");if(Q<0)throw RangeError("Index out of range")}function R9($,q,Q,K,J){if(q=+q,Q=Q>>>0,!J)f9($,q,Q,4,340282346638528860000000000000000000000,-340282346638528860000000000000000000000);return F9($,q,Q,K,23,4),Q+4}function I9($,q,Q,K,J){if(q=+q,Q=Q>>>0,!J)f9($,q,Q,8,179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,-179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);return F9($,q,Q,K,52,8),Q+8}function z9($){let q="",Q=$.length,K=$[0]==="-"?1:0;for(;Q>=K+4;Q-=3)q=`_${$.slice(Q-3,Q)}${q}`;return`${$.slice(0,Q)}${q}`}function KV($,q,Q){if(n1(q,"offset"),$[q]===void 0||$[q+Q]===void 0)h6(q,$.length-(Q+1))}function C9($,q,Q,K,J,Z){if($>Q||$3)if(q===0||q===BigInt(0))W=`>= 0${G} and < 2${G} ** ${(Z+1)*8}${G}`;else W=`>= -(2${G} ** ${(Z+1)*8-1}${G}) and < 2 ** ${(Z+1)*8-1}${G}`;else W=`>= ${q}${G} and <= ${Q}${G}`;throw new g5("value",W,$)}KV(K,J,Z)}function n1($,q){if(typeof $!=="number")throw new cJ(q,"number",$)}function h6($,q,Q){if(Math.floor($)!==$)throw n1($,Q),new g5(Q||"offset","an integer",$);if(q<0)throw new _J;throw new g5(Q||"offset",`>= ${Q?1:0} and <= ${q}`,$)}function VV($){if($=$.split("=")[0],$=$.trim().replace(JV,""),$.length<2)return"";while($.length%4!==0)$=$+"=";return $}function y5($,q){q=q||1/0;let Q,K=$.length,J=null,Z=[];for(let G=0;G55295&&Q<57344){if(!J){if(Q>56319){if((q-=3)>-1)Z.push(239,191,189);continue}else if(G+1===K){if((q-=3)>-1)Z.push(239,191,189);continue}J=Q;continue}if(Q<56320){if((q-=3)>-1)Z.push(239,191,189);J=Q;continue}Q=(J-55296<<10|Q-56320)+65536}else if(J){if((q-=3)>-1)Z.push(239,191,189)}if(J=null,Q<128){if((q-=1)<0)break;Z.push(Q)}else if(Q<2048){if((q-=2)<0)break;Z.push(Q>>6|192,Q&63|128)}else if(Q<65536){if((q-=3)<0)break;Z.push(Q>>12|224,Q>>6&63|128,Q&63|128)}else if(Q<1114112){if((q-=4)<0)break;Z.push(Q>>18|240,Q>>12&63|128,Q>>6&63|128,Q&63|128)}else throw Error("Invalid code point")}return Z}function UV($){let q=[];for(let Q=0;Q<$.length;++Q)q.push($.charCodeAt(Q)&255);return q}function ZV($,q){let Q,K,J,Z=[];for(let G=0;G<$.length;++G){if((q-=2)<0)break;Q=$.charCodeAt(G),K=Q>>8,J=Q%256,Z.push(J),Z.push(K)}return Z}function j9($){return hJ(VV($))}function Y8($,q,Q,K){let J;for(J=0;J=q.length||J>=$.length)break;q[J+Q]=$[J]}return J}function C2($,q){return $ instanceof q||$!=null&&$.constructor!=null&&$.constructor.name!=null&&$.constructor.name===q.name}function l2($){return typeof BigInt>"u"?WV:$}function WV(){throw Error("BigInt not supported")}function P5($){return()=>{throw Error($+" is not implemented for node:buffer browser polyfill")}}var I2,F2,j5="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",M1,U9,G9,M9=50,y6=2147483647,w9=536870888,PJ,TJ,uJ,SJ,EJ,_J,cJ,g5,B9=4096,JV,GV,BV,zV,FV=($)=>{for(let q of $)if(q.charCodeAt(0)>127)return!1;return!0},MV,wV;var t0=b1(()=>{I2=[],F2=[];for(M1=0,U9=j5.length;M14294967296)J=z9(String(Q));else if(typeof Q==="bigint"){if(J=String(Q),Q>BigInt(2)**BigInt(32)||Q<-(BigInt(2)**BigInt(32)))J=z9(J);J+="n"}return K+=` It must be ${q}. Received ${J}`,K},RangeError);Object.defineProperty(o.prototype,"parent",{enumerable:!0,get:function(){if(!o.isBuffer(this))return;return this.buffer}});Object.defineProperty(o.prototype,"offset",{enumerable:!0,get:function(){if(!o.isBuffer(this))return;return this.byteOffset}});o.poolSize=8192;o.from=function($,q,Q){return N9($,q,Q)};Object.setPrototypeOf(o.prototype,Uint8Array.prototype);Object.setPrototypeOf(o,Uint8Array);o.alloc=function($,q,Q){return bJ($,q,Q)};o.allocUnsafe=function($){return x5($)};o.allocUnsafeSlow=function($){return x5($)};o.isBuffer=function($){return $!=null&&$._isBuffer===!0&&$!==o.prototype};o.compare=function($,q){if(C2($,Uint8Array))$=o.from($,$.offset,$.byteLength);if(C2(q,Uint8Array))q=o.from(q,q.offset,q.byteLength);if(!o.isBuffer($)||!o.isBuffer(q))throw TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if($===q)return 0;let Q=$.length,K=q.length;for(let J=0,Z=Math.min(Q,K);JK.length){if(!o.isBuffer(Z))Z=o.from(Z);Z.copy(K,J)}else Uint8Array.prototype.set.call(K,Z,J);else if(!o.isBuffer(Z))throw TypeError('"list" argument must be an Array of Buffers');else Z.copy(K,J);J+=Z.length}return K};o.byteLength=k9;o.prototype._isBuffer=!0;o.prototype.swap16=function(){let $=this.length;if($%2!==0)throw RangeError("Buffer size must be a multiple of 16-bits");for(let q=0;q<$;q+=2)w1(this,q,q+1);return this};o.prototype.swap32=function(){let $=this.length;if($%4!==0)throw RangeError("Buffer size must be a multiple of 32-bits");for(let q=0;q<$;q+=4)w1(this,q,q+3),w1(this,q+1,q+2);return this};o.prototype.swap64=function(){let $=this.length;if($%8!==0)throw RangeError("Buffer size must be a multiple of 64-bits");for(let q=0;q<$;q+=8)w1(this,q,q+7),w1(this,q+1,q+6),w1(this,q+2,q+5),w1(this,q+3,q+4);return this};o.prototype.toString=function(){let $=this.length;if($===0)return"";if(arguments.length===0)return L9(this,0,$);return pJ.apply(this,arguments)};o.prototype.toLocaleString=o.prototype.toString;o.prototype.equals=function($){if(!o.isBuffer($))throw TypeError("Argument must be a Buffer");if(this===$)return!0;return o.compare(this,$)===0};o.prototype.inspect=function(){let $="",q=M9;if($=this.toString("hex",0,q).replace(/(.{2})/g,"$1 ").trim(),this.length>q)$+=" ... ";return""};if(G9)o.prototype[G9]=o.prototype.inspect;o.prototype.compare=function($,q,Q,K,J){if(C2($,Uint8Array))$=o.from($,$.offset,$.byteLength);if(!o.isBuffer($))throw TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof $);if(q===void 0)q=0;if(Q===void 0)Q=$?$.length:0;if(K===void 0)K=0;if(J===void 0)J=this.length;if(q<0||Q>$.length||K<0||J>this.length)throw RangeError("out of range index");if(K>=J&&q>=Q)return 0;if(K>=J)return-1;if(q>=Q)return 1;if(q>>>=0,Q>>>=0,K>>>=0,J>>>=0,this===$)return 0;let Z=J-K,G=Q-q,W=Math.min(Z,G),B=this.slice(K,J),V=$.slice(q,Q);for(let U=0;U>>0,isFinite(Q)){if(Q=Q>>>0,K===void 0)K="utf8"}else K=Q,Q=void 0;else throw Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let J=this.length-q;if(Q===void 0||Q>J)Q=J;if($.length>0&&(Q<0||q<0)||q>this.length)throw RangeError("Attempt to write outside buffer bounds");if(!K)K="utf8";let Z=!1;for(;;)switch(K){case"hex":return iJ(this,$,q,Q);case"utf8":case"utf-8":return oJ(this,$,q,Q);case"ascii":case"latin1":case"binary":return aJ(this,$,q,Q);case"base64":return lJ(this,$,q,Q);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return rJ(this,$,q,Q);default:if(Z)throw TypeError("Unknown encoding: "+K);K=(""+K).toLowerCase(),Z=!0}};o.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};o.prototype.slice=function($,q){let Q=this.length;if($=~~$,q=q===void 0?Q:~~q,$<0){if($+=Q,$<0)$=0}else if($>Q)$=Q;if(q<0){if(q+=Q,q<0)q=0}else if(q>Q)q=Q;if(q<$)q=$;let K=this.subarray($,q);return Object.setPrototypeOf(K,o.prototype),K};o.prototype.readUintLE=o.prototype.readUIntLE=function($,q,Q){if($=$>>>0,q=q>>>0,!Q)b0($,q,this.length);let K=this[$],J=1,Z=0;while(++Z>>0,q=q>>>0,!Q)b0($,q,this.length);let K=this[$+--q],J=1;while(q>0&&(J*=256))K+=this[$+--q]*J;return K};o.prototype.readUint8=o.prototype.readUInt8=function($,q){if($=$>>>0,!q)b0($,1,this.length);return this[$]};o.prototype.readUint16LE=o.prototype.readUInt16LE=function($,q){if($=$>>>0,!q)b0($,2,this.length);return this[$]|this[$+1]<<8};o.prototype.readUint16BE=o.prototype.readUInt16BE=function($,q){if($=$>>>0,!q)b0($,2,this.length);return this[$]<<8|this[$+1]};o.prototype.readUint32LE=o.prototype.readUInt32LE=function($,q){if($=$>>>0,!q)b0($,4,this.length);return(this[$]|this[$+1]<<8|this[$+2]<<16)+this[$+3]*16777216};o.prototype.readUint32BE=o.prototype.readUInt32BE=function($,q){if($=$>>>0,!q)b0($,4,this.length);return this[$]*16777216+(this[$+1]<<16|this[$+2]<<8|this[$+3])};o.prototype.readBigUInt64LE=l2(function($){$=$>>>0,n1($,"offset");let q=this[$],Q=this[$+7];if(q===void 0||Q===void 0)h6($,this.length-8);let K=q+this[++$]*256+this[++$]*65536+this[++$]*16777216,J=this[++$]+this[++$]*256+this[++$]*65536+Q*16777216;return BigInt(K)+(BigInt(J)<>>0,n1($,"offset");let q=this[$],Q=this[$+7];if(q===void 0||Q===void 0)h6($,this.length-8);let K=q*16777216+this[++$]*65536+this[++$]*256+this[++$],J=this[++$]*16777216+this[++$]*65536+this[++$]*256+Q;return(BigInt(K)<>>0,q=q>>>0,!Q)b0($,q,this.length);let K=this[$],J=1,Z=0;while(++Z=J)K-=Math.pow(2,8*q);return K};o.prototype.readIntBE=function($,q,Q){if($=$>>>0,q=q>>>0,!Q)b0($,q,this.length);let K=q,J=1,Z=this[$+--K];while(K>0&&(J*=256))Z+=this[$+--K]*J;if(J*=128,Z>=J)Z-=Math.pow(2,8*q);return Z};o.prototype.readInt8=function($,q){if($=$>>>0,!q)b0($,1,this.length);if(!(this[$]&128))return this[$];return(255-this[$]+1)*-1};o.prototype.readInt16LE=function($,q){if($=$>>>0,!q)b0($,2,this.length);let Q=this[$]|this[$+1]<<8;return Q&32768?Q|4294901760:Q};o.prototype.readInt16BE=function($,q){if($=$>>>0,!q)b0($,2,this.length);let Q=this[$+1]|this[$]<<8;return Q&32768?Q|4294901760:Q};o.prototype.readInt32LE=function($,q){if($=$>>>0,!q)b0($,4,this.length);return this[$]|this[$+1]<<8|this[$+2]<<16|this[$+3]<<24};o.prototype.readInt32BE=function($,q){if($=$>>>0,!q)b0($,4,this.length);return this[$]<<24|this[$+1]<<16|this[$+2]<<8|this[$+3]};o.prototype.readBigInt64LE=l2(function($){$=$>>>0,n1($,"offset");let q=this[$],Q=this[$+7];if(q===void 0||Q===void 0)h6($,this.length-8);let K=this[$+4]+this[$+5]*256+this[$+6]*65536+(Q<<24);return(BigInt(K)<>>0,n1($,"offset");let q=this[$],Q=this[$+7];if(q===void 0||Q===void 0)h6($,this.length-8);let K=(q<<24)+this[++$]*65536+this[++$]*256+this[++$];return(BigInt(K)<>>0,!q)b0($,4,this.length);return N8(this,$,!0,23,4)};o.prototype.readFloatBE=function($,q){if($=$>>>0,!q)b0($,4,this.length);return N8(this,$,!1,23,4)};o.prototype.readDoubleLE=function($,q){if($=$>>>0,!q)b0($,8,this.length);return N8(this,$,!0,52,8)};o.prototype.readDoubleBE=function($,q){if($=$>>>0,!q)b0($,8,this.length);return N8(this,$,!1,52,8)};o.prototype.writeUintLE=o.prototype.writeUIntLE=function($,q,Q,K){if($=+$,q=q>>>0,Q=Q>>>0,!K){let G=Math.pow(2,8*Q)-1;s0(this,$,q,Q,G,0)}let J=1,Z=0;this[q]=$&255;while(++Z>>0,Q=Q>>>0,!K){let G=Math.pow(2,8*Q)-1;s0(this,$,q,Q,G,0)}let J=Q-1,Z=1;this[q+J]=$&255;while(--J>=0&&(Z*=256))this[q+J]=$/Z&255;return q+Q};o.prototype.writeUint8=o.prototype.writeUInt8=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,1,255,0);return this[q]=$&255,q+1};o.prototype.writeUint16LE=o.prototype.writeUInt16LE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,2,65535,0);return this[q]=$&255,this[q+1]=$>>>8,q+2};o.prototype.writeUint16BE=o.prototype.writeUInt16BE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,2,65535,0);return this[q]=$>>>8,this[q+1]=$&255,q+2};o.prototype.writeUint32LE=o.prototype.writeUInt32LE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,4,4294967295,0);return this[q+3]=$>>>24,this[q+2]=$>>>16,this[q+1]=$>>>8,this[q]=$&255,q+4};o.prototype.writeUint32BE=o.prototype.writeUInt32BE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,4,4294967295,0);return this[q]=$>>>24,this[q+1]=$>>>16,this[q+2]=$>>>8,this[q+3]=$&255,q+4};o.prototype.writeBigUInt64LE=l2(function($,q=0){return H9(this,$,q,BigInt(0),BigInt("0xffffffffffffffff"))});o.prototype.writeBigUInt64BE=l2(function($,q=0){return v9(this,$,q,BigInt(0),BigInt("0xffffffffffffffff"))});o.prototype.writeIntLE=function($,q,Q,K){if($=+$,q=q>>>0,!K){let W=Math.pow(2,8*Q-1);s0(this,$,q,Q,W-1,-W)}let J=0,Z=1,G=0;this[q]=$&255;while(++J>0)-G&255}return q+Q};o.prototype.writeIntBE=function($,q,Q,K){if($=+$,q=q>>>0,!K){let W=Math.pow(2,8*Q-1);s0(this,$,q,Q,W-1,-W)}let J=Q-1,Z=1,G=0;this[q+J]=$&255;while(--J>=0&&(Z*=256)){if($<0&&G===0&&this[q+J+1]!==0)G=1;this[q+J]=($/Z>>0)-G&255}return q+Q};o.prototype.writeInt8=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,1,127,-128);if($<0)$=255+$+1;return this[q]=$&255,q+1};o.prototype.writeInt16LE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,2,32767,-32768);return this[q]=$&255,this[q+1]=$>>>8,q+2};o.prototype.writeInt16BE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,2,32767,-32768);return this[q]=$>>>8,this[q+1]=$&255,q+2};o.prototype.writeInt32LE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,4,2147483647,-2147483648);return this[q]=$&255,this[q+1]=$>>>8,this[q+2]=$>>>16,this[q+3]=$>>>24,q+4};o.prototype.writeInt32BE=function($,q,Q){if($=+$,q=q>>>0,!Q)s0(this,$,q,4,2147483647,-2147483648);if($<0)$=4294967295+$+1;return this[q]=$>>>24,this[q+1]=$>>>16,this[q+2]=$>>>8,this[q+3]=$&255,q+4};o.prototype.writeBigInt64LE=l2(function($,q=0){return H9(this,$,q,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))});o.prototype.writeBigInt64BE=l2(function($,q=0){return v9(this,$,q,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))});o.prototype.writeFloatLE=function($,q,Q){return R9(this,$,q,!0,Q)};o.prototype.writeFloatBE=function($,q,Q){return R9(this,$,q,!1,Q)};o.prototype.writeDoubleLE=function($,q,Q){return I9(this,$,q,!0,Q)};o.prototype.writeDoubleBE=function($,q,Q){return I9(this,$,q,!1,Q)};o.prototype.copy=function($,q,Q,K){if(!o.isBuffer($))throw TypeError("argument should be a Buffer");if(!Q)Q=0;if(!K&&K!==0)K=this.length;if(q>=$.length)q=$.length;if(!q)q=0;if(K>0&&K=this.length)throw RangeError("Index out of range");if(K<0)throw RangeError("sourceEnd out of bounds");if(K>this.length)K=this.length;if($.length-q>>0,Q=Q===void 0?this.length:Q>>>0,!$)$=0;let J;if(typeof $==="number")for(J=q;J{var S0=y9.exports={},j2,g2;function T5(){throw Error("setTimeout has not been defined")}function u5(){throw Error("clearTimeout has not been defined")}(function(){try{if(typeof setTimeout==="function")j2=setTimeout;else j2=T5}catch($){j2=T5}try{if(typeof clearTimeout==="function")g2=clearTimeout;else g2=u5}catch($){g2=u5}})();function g9($){if(j2===setTimeout)return setTimeout($,0);if((j2===T5||!j2)&&setTimeout)return j2=setTimeout,setTimeout($,0);try{return j2($,0)}catch(q){try{return j2.call(null,$,0)}catch(Q){return j2.call(this,$,0)}}}function NV($){if(g2===clearTimeout)return clearTimeout($);if((g2===u5||!g2)&&clearTimeout)return g2=clearTimeout,clearTimeout($);try{return g2($)}catch(q){try{return g2.call(null,$)}catch(Q){return g2.call(this,$)}}}var E2=[],d1=!1,N1,k8=-1;function YV(){if(!d1||!N1)return;if(d1=!1,N1.length)E2=N1.concat(E2);else k8=-1;if(E2.length)A9()}function A9(){if(d1)return;var $=g9(YV);d1=!0;var q=E2.length;while(q){N1=E2,E2=[];while(++k81)for(var Q=1;Qn9,once:()=>c9,listenerCount:()=>d9,init:()=>r2,getMaxListeners:()=>p9,getEventListeners:()=>b9,default:()=>CV,captureRejectionSymbol:()=>u9,addAbortListener:()=>i9,EventEmitter:()=>r2});function S9($,q){var{_events:Q}=$;if(q[0]??=Error("Unhandled error."),!Q)throw q[0];var K=Q[T9];if(K)for(var J of O9.call(K))J.apply($,q);var Z=Q.error;if(!Z)throw q[0];for(var J of O9.call(Z))J.apply($,q);return!0}function LV($,q,Q,K){q.then(void 0,function(J){queueMicrotask(()=>HV($,J,Q,K))})}function HV($,q,Q,K){if(typeof $[x9]==="function")$[x9](q,Q,...K);else try{$[Y1]=!1,$.emit("error",q)}finally{$[Y1]=!0}}function E9($,q,Q){Q.warned=!0;let K=Error(`Possible EventEmitter memory leak detected. ${Q.length} ${String(q)} listeners added to [${$.constructor.name}]. Use emitter.setMaxListeners() to increase limit`);K.name="MaxListenersExceededWarning",K.emitter=$,K.type=q,K.count=Q.length,console.warn(K)}function _9($,q,...Q){this.removeListener($,q),q.apply(this,Q)}function c9($,q,Q){var K=Q?.signal;if(m9(K,"options.signal"),K?.aborted)throw new S5(void 0,{cause:K?.reason});let{resolve:J,reject:Z,promise:G}=$newPromiseCapability(Promise),W=(U)=>{if($.removeListener(q,B),K!=null)D8(K,"abort",V);Z(U)},B=(...U)=>{if(typeof $.removeListener==="function")$.removeListener("error",W);if(K!=null)D8(K,"abort",V);J(U)};if(P9($,q,B,{once:!0}),q!=="error"&&typeof $.once==="function")$.once("error",W);function V(){D8($,q,B),D8($,"error",W),Z(new S5(void 0,{cause:K?.reason}))}if(K!=null)P9(K,"abort",V,{once:!0});return G}function b9($,q){return $.listeners(q)}function n9($,...q){_5($,"setMaxListeners",0);var Q;if(q&&(Q=q.length))for(let K=0;KK||(Q!=null||K!=null)&&Number.isNaN($))throw RV(q,`${Q!=null?`>= ${Q}`:""}${Q!=null&&K!=null?" && ":""}${K!=null?`<= ${K}`:""}`,$)}function x6($){if(typeof $!=="function")throw TypeError("The listener must be a function")}function IV($,q){if(typeof $!=="boolean")throw m1(q,"boolean",$)}function p9($){return $?._maxListeners??k1}function i9($,q){if($===void 0)throw m1("signal","AbortSignal",$);if(m9($,"signal"),typeof q!=="function")throw m1("listener","function",q);let Q;if($.aborted)queueMicrotask(()=>q());else $.addEventListener("abort",q,{__proto__:null,once:!0}),Q=()=>{$.removeEventListener("abort",q)};return{__proto__:null,[Symbol.dispose](){Q?.()}}}var E5,Y1,T9,kV,DV,x9,u9,O9,k1=10,r2=function($){if(this._events===void 0||this._events===this.__proto__._events)this._events={__proto__:null},this._eventsCount=0;if(this._maxListeners??=void 0,this[Y1]=$?.captureRejections?Boolean($?.captureRejections):y0[Y1])this.emit=fV},y0,vV=function($,...q){if($==="error")return S9(this,q);var{_events:Q}=this;if(Q===void 0)return!1;var K=Q[$];if(K===void 0)return!1;let J=K.length>1?K.slice():K;for(let Z=0,{length:G}=J;Z1?K.slice():K;for(let Z=0,{length:G}=J;Z{E5=Symbol.for,Y1=Symbol("kCapture"),T9=E5("events.errorMonitor"),kV=Symbol("events.maxEventTargetListeners"),DV=Symbol("events.maxEventTargetListenersWarned"),x9=E5("nodejs.rejection"),u9=E5("nodejs.rejection"),O9=Array.prototype.slice,y0=r2.prototype={};y0._events=void 0;y0._eventsCount=0;y0._maxListeners=void 0;y0.setMaxListeners=function($){return _5($,"setMaxListeners",0),this._maxListeners=$,this};y0.constructor=r2;y0.getMaxListeners=function(){return this?._maxListeners??k1};y0.emit=vV;y0.addListener=function($,q){x6(q);var Q=this._events;if(!Q)Q=this._events={__proto__:null},this._eventsCount=0;else if(Q.newListener)this.emit("newListener",$,q.listener??q);var K=Q[$];if(!K)Q[$]=[q],this._eventsCount++;else{K.push(q);var J=this._maxListeners??k1;if(J>0&&K.length>J&&!K.warned)E9(this,$,K)}return this};y0.on=y0.addListener;y0.prependListener=function($,q){x6(q);var Q=this._events;if(!Q)Q=this._events={__proto__:null},this._eventsCount=0;else if(Q.newListener)this.emit("newListener",$,q.listener??q);var K=Q[$];if(!K)Q[$]=[q],this._eventsCount++;else{K.unshift(q);var J=this._maxListeners??k1;if(J>0&&K.length>J&&!K.warned)E9(this,$,K)}return this};y0.once=function($,q){x6(q);let Q=_9.bind(this,$,q);return Q.listener=q,this.addListener($,Q),this};y0.prependOnceListener=function($,q){x6(q);let Q=_9.bind(this,$,q);return Q.listener=q,this.prependListener($,Q),this};y0.removeListener=function($,q){x6(q);var{_events:Q}=this;if(!Q)return this;var K=Q[$];if(!K)return this;var J=K.length;let Z=-1;for(let G=J-1;G>=0;G--)if(K[G]===q||K[G].listener===q){Z=G;break}if(Z<0)return this;if(Z===0)K.shift();else K.splice(Z,1);if(K.length===0)delete Q[$],this._eventsCount--;return this};y0.off=y0.removeListener;y0.removeAllListeners=function($){var{_events:q}=this;if($&&q){if(q[$])delete q[$],this._eventsCount--}else this._events={__proto__:null};return this};y0.listeners=function($){var{_events:q}=this;if(!q)return[];var Q=q[$];if(!Q)return[];return Q.map((K)=>K.listener??K)};y0.rawListeners=function($){var{_events:q}=this;if(!q)return[];var Q=q[$];if(!Q)return[];return Q.slice()};y0.listenerCount=function($){var{_events:q}=this;if(!q)return 0;return q[$]?.length??0};y0.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};y0[Y1]=!1;S5=class S5 extends Error{constructor($="The operation was aborted",q=void 0){if(q!==void 0&&typeof q!=="object")throw m1("options","Object",q);super($,q);this.code="ABORT_ERR",this.name="AbortError"}};Object.defineProperties(r2,{captureRejections:{get(){return y0[Y1]},set($){IV($,"EventEmitter.captureRejections"),y0[Y1]=$},enumerable:!0},defaultMaxListeners:{enumerable:!0,get:()=>{return k1},set:($)=>{_5($,"defaultMaxListeners",0),k1=$}},kMaxEventTargetListeners:{value:kV,enumerable:!1,configurable:!1,writable:!1},kMaxEventTargetListenersWarned:{value:DV,enumerable:!1,configurable:!1,writable:!1}});Object.assign(r2,{once:c9,getEventListeners:b9,getMaxListeners:p9,setMaxListeners:n9,EventEmitter:r2,usingDomains:!1,captureRejectionSymbol:u9,errorMonitor:T9,addAbortListener:i9,init:r2,listenerCount:d9});CV=r2});var a1=N0((Yz,$$)=>{var g0=($,q)=>()=>(q||$((q={exports:{}}).exports,q),q.exports),P0=g0(($,q)=>{class Q extends Error{constructor(K){if(!Array.isArray(K))throw TypeError(`Expected input to be an Array, got ${typeof K}`);let J="";for(let Z=0;Z{q.exports={format(Q,...K){return Q.replace(/%([sdifj])/g,function(...[J,Z]){let G=K.shift();if(Z==="f")return G.toFixed(6);else if(Z==="j")return JSON.stringify(G);else if(Z==="s"&&typeof G==="object")return`${G.constructor!==Object?G.constructor.name:""} {}`.trim();else return G.toString()})},inspect(Q){switch(typeof Q){case"string":if(Q.includes("'")){if(!Q.includes('"'))return`"${Q}"`;else if(!Q.includes("`")&&!Q.includes("${"))return`\`${Q}\``}return`'${Q}'`;case"number":if(isNaN(Q))return"NaN";else if(Object.is(Q,-0))return String(Q);return Q;case"bigint":return`${String(Q)}n`;case"boolean":case"undefined":return String(Q);case"object":return"{}"}}}}),a0=g0(($,q)=>{var{format:Q,inspect:K}=o9(),{AggregateError:J}=P0(),Z=globalThis.AggregateError||J,G=Symbol("kIsNodeError"),W=["string","function","number","object","Function","Object","boolean","bigint","symbol"],B=/^([A-Z][a-z0-9]*)+$/,V={};function U(D,z){if(!D)throw new V.ERR_INTERNAL_ASSERTION(z)}function w(D){let z="",N=D.length,H=D[0]==="-"?1:0;for(;N>=H+4;N-=3)z=`_${D.slice(N-3,N)}${z}`;return`${D.slice(0,N)}${z}`}function F(D,z,N){if(typeof z==="function")return U(z.length<=N.length,`Code: ${D}; The provided arguments length (${N.length}) does not match the required ones (${z.length}).`),z(...N);let H=(z.match(/%[dfijoOs]/g)||[]).length;if(U(H===N.length,`Code: ${D}; The provided arguments length (${N.length}) does not match the required ones (${H}).`),N.length===0)return z;return Q(z,...N)}function M(D,z,N){if(!N)N=Error;class H extends N{constructor(...v){super(F(D,z,v))}toString(){return`${this.name} [${D}]: ${this.message}`}}Object.defineProperties(H.prototype,{name:{value:N.name,writable:!0,enumerable:!1,configurable:!0},toString:{value(){return`${this.name} [${D}]: ${this.message}`},writable:!0,enumerable:!1,configurable:!0}}),H.prototype.code=D,H.prototype[G]=!0,V[D]=H}function k(D){let z="__node_internal_"+D.name;return Object.defineProperty(D,"name",{value:z}),D}function f(D,z){if(D&&z&&D!==z){if(Array.isArray(z.errors))return z.errors.push(D),z;let N=new Z([z,D],z.message);return N.code=z.code,N}return D||z}class L extends Error{constructor(D="The operation was aborted",z=void 0){if(z!==void 0&&typeof z!=="object")throw new V.ERR_INVALID_ARG_TYPE("options","Object",z);super(D,z);this.code="ABORT_ERR",this.name="AbortError"}}M("ERR_ASSERTION","%s",Error),M("ERR_INVALID_ARG_TYPE",(D,z,N)=>{if(U(typeof D==="string","'name' must be a string"),!Array.isArray(z))z=[z];let H="The ";if(D.endsWith(" argument"))H+=`${D} `;else H+=`"${D}" ${D.includes(".")?"property":"argument"} `;H+="must be ";let v=[],j=[],n=[];for(let _ of z)if(U(typeof _==="string","All expected entries have to be of type string"),W.includes(_))v.push(_.toLowerCase());else if(B.test(_))j.push(_);else U(_!=="object",'The value "object" should be written as "Object"'),n.push(_);if(j.length>0){let _=v.indexOf("object");if(_!==-1)v.splice(v,_,1),j.push("Object")}if(v.length>0){switch(v.length){case 1:H+=`of type ${v[0]}`;break;case 2:H+=`one of type ${v[0]} or ${v[1]}`;break;default:{let _=v.pop();H+=`one of type ${v.join(", ")}, or ${_}`}}if(j.length>0||n.length>0)H+=" or "}if(j.length>0){switch(j.length){case 1:H+=`an instance of ${j[0]}`;break;case 2:H+=`an instance of ${j[0]} or ${j[1]}`;break;default:{let _=j.pop();H+=`an instance of ${j.join(", ")}, or ${_}`}}if(n.length>0)H+=" or "}switch(n.length){case 0:break;case 1:if(n[0].toLowerCase()!==n[0])H+="an ";H+=`${n[0]}`;break;case 2:H+=`one of ${n[0]} or ${n[1]}`;break;default:{let _=n.pop();H+=`one of ${n.join(", ")}, or ${_}`}}if(N==null)H+=`. Received ${N}`;else if(typeof N==="function"&&N.name)H+=`. Received function ${N.name}`;else if(typeof N==="object"){var d;if((d=N.constructor)!==null&&d!==void 0&&d.name)H+=`. Received an instance of ${N.constructor.name}`;else{let _=K(N,{depth:-1});H+=`. Received ${_}`}}else{let _=K(N,{colors:!1});if(_.length>25)_=`${_.slice(0,25)}...`;H+=`. Received type ${typeof N} (${_})`}return H},TypeError),M("ERR_INVALID_ARG_VALUE",(D,z,N="is invalid")=>{let H=K(z);if(H.length>128)H=H.slice(0,128)+"...";return`The ${D.includes(".")?"property":"argument"} '${D}' ${N}. Received ${H}`},TypeError),M("ERR_INVALID_RETURN_VALUE",(D,z,N)=>{var H;let v=N!==null&&N!==void 0&&(H=N.constructor)!==null&&H!==void 0&&H.name?`instance of ${N.constructor.name}`:`type ${typeof N}`;return`Expected ${D} to be returned from the "${z}" function but got ${v}.`},TypeError),M("ERR_MISSING_ARGS",(...D)=>{U(D.length>0,"At least one arg needs to be specified");let z,N=D.length;switch(D=(Array.isArray(D)?D:[D]).map((H)=>`"${H}"`).join(" or "),N){case 1:z+=`The ${D[0]} argument`;break;case 2:z+=`The ${D[0]} and ${D[1]} arguments`;break;default:{let H=D.pop();z+=`The ${D.join(", ")}, and ${H} arguments`}break}return`${z} must be specified`},TypeError),M("ERR_OUT_OF_RANGE",(D,z,N)=>{U(z,'Missing "range" argument');let H;if(Number.isInteger(N)&&Math.abs(N)>4294967296)H=w(String(N));else if(typeof N==="bigint"){H=String(N);let v=BigInt(2)**BigInt(32);if(N>v||N<-v)H=w(H);H+="n"}else H=K(N);return`The value of "${D}" is out of range. It must be ${z}. Received ${H}`},RangeError),M("ERR_MULTIPLE_CALLBACK","Callback called multiple times",Error),M("ERR_METHOD_NOT_IMPLEMENTED","The %s method is not implemented",Error),M("ERR_STREAM_ALREADY_FINISHED","Cannot call %s after a stream was finished",Error),M("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable",Error),M("ERR_STREAM_DESTROYED","Cannot call %s after a stream was destroyed",Error),M("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),M("ERR_STREAM_PREMATURE_CLOSE","Premature close",Error),M("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF",Error),M("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event",Error),M("ERR_STREAM_WRITE_AFTER_END","write after end",Error),M("ERR_UNKNOWN_ENCODING","Unknown encoding: %s",TypeError),q.exports={AbortError:L,aggregateTwoErrors:k(f),hideStackFrames:k,codes:V}}),jV=g0(($,q)=>{Object.defineProperty($,"__esModule",{value:!0});var Q=new WeakMap,K=new WeakMap;function J(X){let P=Q.get(X);return console.assert(P!=null,"'this' is expected an Event object, but got",X),P}function Z(X){if(X.passiveListener!=null){if(typeof console<"u"&&typeof console.error==="function")console.error("Unable to preventDefault inside passive event listener invocation.",X.passiveListener);return}if(!X.event.cancelable)return;if(X.canceled=!0,typeof X.event.preventDefault==="function")X.event.preventDefault()}function G(X,P){Q.set(this,{eventTarget:X,event:P,eventPhase:2,currentTarget:X,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:P.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});let g=Object.keys(P);for(let c=0;c0){let X=Array(arguments.length);for(let P=0;P{Object.defineProperty($,"__esModule",{value:!0});var Q=jV();class K extends Q.EventTarget{constructor(){super();throw TypeError("AbortSignal cannot be constructed directly")}get aborted(){let U=G.get(this);if(typeof U!=="boolean")throw TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this===null?"null":typeof this}`);return U}}Q.defineEventAttribute(K.prototype,"abort");function J(){let U=Object.create(K.prototype);return Q.EventTarget.call(U),G.set(U,!1),U}function Z(U){if(G.get(U)!==!1)return;G.set(U,!0),U.dispatchEvent({type:"abort"})}var G=new WeakMap;if(Object.defineProperties(K.prototype,{aborted:{enumerable:!0}}),typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol")Object.defineProperty(K.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortSignal"});class W{constructor(){B.set(this,J())}get signal(){return V(this)}abort(){Z(V(this))}}var B=new WeakMap;function V(U){let w=B.get(U);if(w==null)throw TypeError(`Expected 'this' to be an 'AbortController' object, but got ${U===null?"null":typeof U}`);return w}if(Object.defineProperties(W.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol")Object.defineProperty(W.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortController"});$.AbortController=W,$.AbortSignal=K,$.default=W,q.exports=W,q.exports.AbortController=q.exports.default=W,q.exports.AbortSignal=K}),e0=g0(($,q)=>{var Q=(t0(),X0(K2)),{format:K,inspect:J}=o9(),{codes:{ERR_INVALID_ARG_TYPE:Z}}=a0(),{kResistStopPropagation:G,AggregateError:W,SymbolDispose:B}=P0(),V=globalThis.AbortSignal||O6().AbortSignal,U=globalThis.AbortController||O6().AbortController,w=Object.getPrototypeOf(async function(){}).constructor,F=globalThis.Blob||Q.Blob,M=typeof F<"u"?function(L){return L instanceof F}:function(L){return!1},k=(L,D)=>{if(L!==void 0&&(L===null||typeof L!=="object"||!("aborted"in L)))throw new Z(D,"AbortSignal",L)},f=(L,D)=>{if(typeof L!=="function")throw new Z(D,"Function",L)};q.exports={AggregateError:W,kEmptyObject:Object.freeze({}),once(L){let D=!1;return function(...z){if(D)return;D=!0,L.apply(this,z)}},createDeferredPromise:function(){let L,D;return{promise:new Promise((z,N)=>{L=z,D=N}),resolve:L,reject:D}},promisify(L){return new Promise((D,z)=>{L((N,...H)=>{if(N)return z(N);return D(...H)})})},debuglog(){return function(){}},format:K,inspect:J,types:{isAsyncFunction(L){return L instanceof w},isArrayBufferView(L){return ArrayBuffer.isView(L)}},isBlob:M,deprecate(L,D){return L},addAbortListener:(i1(),X0(p1)).addAbortListener||function(L,D){if(L===void 0)throw new Z("signal","AbortSignal",L);k(L,"signal"),f(D,"listener");let z;if(L.aborted)queueMicrotask(()=>D());else L.addEventListener("abort",D,{__proto__:null,once:!0,[G]:!0}),z=()=>{L.removeEventListener("abort",D)};return{__proto__:null,[B](){var N;(N=z)===null||N===void 0||N()}}},AbortSignalAny:V.any||function(L){if(L.length===1)return L[0];let D=new U,z=()=>D.abort();return L.forEach((N)=>{k(N,"signals"),N.addEventListener("abort",z,{once:!0})}),D.signal.addEventListener("abort",()=>{L.forEach((N)=>N.removeEventListener("abort",z))},{once:!0}),D.signal}},q.exports.promisify.custom=Symbol.for("nodejs.util.promisify.custom")}),P6=g0(($,q)=>{var{ArrayIsArray:Q,ArrayPrototypeIncludes:K,ArrayPrototypeJoin:J,ArrayPrototypeMap:Z,NumberIsInteger:G,NumberIsNaN:W,NumberMAX_SAFE_INTEGER:B,NumberMIN_SAFE_INTEGER:V,NumberParseInt:U,ObjectPrototypeHasOwnProperty:w,RegExpPrototypeExec:F,String:M,StringPrototypeToUpperCase:k,StringPrototypeTrim:f}=P0(),{hideStackFrames:L,codes:{ERR_SOCKET_BAD_PORT:D,ERR_INVALID_ARG_TYPE:z,ERR_INVALID_ARG_VALUE:N,ERR_OUT_OF_RANGE:H,ERR_UNKNOWN_SIGNAL:v}}=a0(),{normalizeEncoding:j}=e0(),{isAsyncFunction:n,isArrayBufferView:d}=e0().types,_={};function X(T){return T===(T|0)}function P(T){return T===T>>>0}var g=/^[0-7]+$/,c="must be a 32-bit unsigned integer or an octal string";function h(T,t,G0){if(typeof T>"u")T=G0;if(typeof T==="string"){if(F(g,T)===null)throw new N(t,T,c);T=U(T,8)}return $0(T,t),T}var x=L((T,t,G0=V,Q0=B)=>{if(typeof T!=="number")throw new z(t,"number",T);if(!G(T))throw new H(t,"an integer",T);if(TQ0)throw new H(t,`>= ${G0} && <= ${Q0}`,T)}),l=L((T,t,G0=-2147483648,Q0=2147483647)=>{if(typeof T!=="number")throw new z(t,"number",T);if(!G(T))throw new H(t,"an integer",T);if(TQ0)throw new H(t,`>= ${G0} && <= ${Q0}`,T)}),$0=L((T,t,G0=!1)=>{if(typeof T!=="number")throw new z(t,"number",T);if(!G(T))throw new H(t,"an integer",T);let Q0=G0?1:0,M0=4294967295;if(TM0)throw new H(t,`>= ${Q0} && <= ${M0}`,T)});function Z0(T,t){if(typeof T!=="string")throw new z(t,"string",T)}function F0(T,t,G0=void 0,Q0){if(typeof T!=="number")throw new z(t,"number",T);if(G0!=null&&TQ0||(G0!=null||Q0!=null)&&W(T))throw new H(t,`${G0!=null?`>= ${G0}`:""}${G0!=null&&Q0!=null?" && ":""}${Q0!=null?`<= ${Q0}`:""}`,T)}var p=L((T,t,G0)=>{if(!K(G0,T)){let Q0="must be one of: "+J(Z(G0,(M0)=>typeof M0==="string"?`'${M0}'`:M(M0)),", ");throw new N(t,T,Q0)}});function W0(T,t){if(typeof T!=="boolean")throw new z(t,"boolean",T)}function y(T,t,G0){return T==null||!w(T,t)?G0:T[t]}var i=L((T,t,G0=null)=>{let Q0=y(G0,"allowArray",!1),M0=y(G0,"allowFunction",!1);if(!y(G0,"nullable",!1)&&T===null||!Q0&&Q(T)||typeof T!=="object"&&(!M0||typeof T!=="function"))throw new z(t,"Object",T)}),U0=L((T,t)=>{if(T!=null&&typeof T!=="object"&&typeof T!=="function")throw new z(t,"a dictionary",T)}),m=L((T,t,G0=0)=>{if(!Q(T))throw new z(t,"Array",T);if(T.length{if(!d(T))throw new z(t,["Buffer","TypedArray","DataView"],T)});function E(T,t){let G0=j(t),Q0=T.length;if(G0==="hex"&&Q0%2!==0)throw new N("encoding",t,`is invalid for data of length ${Q0}`)}function a(T,t="Port",G0=!0){if(typeof T!=="number"&&typeof T!=="string"||typeof T==="string"&&f(T).length===0||+T!==+T>>>0||T>65535||T===0&&!G0)throw new D(t,T,G0);return T|0}var K0=L((T,t)=>{if(T!==void 0&&(T===null||typeof T!=="object"||!("aborted"in T)))throw new z(t,"AbortSignal",T)}),R=L((T,t)=>{if(typeof T!=="function")throw new z(t,"Function",T)}),Y=L((T,t)=>{if(typeof T!=="function"||n(T))throw new z(t,"Function",T)}),C=L((T,t)=>{if(T!==void 0)throw new z(t,"undefined",T)});function u(T,t,G0){if(!K(G0,T))throw new z(t,`('${J(G0,"|")}')`,T)}var e=/^(?:<[^>]*>)(?:\s*;\s*[^;"\s]+(?:=(")?[^;"\s]*\1)?)*$/;function r(T,t){if(typeof T>"u"||!F(e,T))throw new N(t,T,'must be an array or string of format "; rel=preload; as=style"')}function s(T){if(typeof T==="string")return r(T,"hints"),T;else if(Q(T)){let t=T.length,G0="";if(t===0)return G0;for(let Q0=0;Q0; rel=preload; as=style"')}q.exports={isInt32:X,isUint32:P,parseFileMode:h,validateArray:m,validateStringArray:V0,validateBooleanArray:w0,validateAbortSignalArray:S,validateBoolean:W0,validateBuffer:O,validateDictionary:U0,validateEncoding:E,validateFunction:R,validateInt32:l,validateInteger:x,validateNumber:F0,validateObject:i,validateOneOf:p,validatePlainFunction:Y,validatePort:a,validateSignalName:b,validateString:Z0,validateUint32:$0,validateUndefined:C,validateUnion:u,validateAbortSignal:K0,validateLinkHeaderValue:s}}),D1=g0(($,q)=>{q.exports=globalThis.process}),b2=g0(($,q)=>{var{SymbolAsyncIterator:Q,SymbolIterator:K,SymbolFor:J}=P0(),Z=J("nodejs.stream.destroyed"),G=J("nodejs.stream.errored"),W=J("nodejs.stream.readable"),B=J("nodejs.stream.writable"),V=J("nodejs.stream.disturbed"),U=J("nodejs.webstream.isClosedPromise"),w=J("nodejs.webstream.controllerErrorFunction");function F(y,i=!1){var U0;return!!(y&&typeof y.pipe==="function"&&typeof y.on==="function"&&(!i||typeof y.pause==="function"&&typeof y.resume==="function")&&(!y._writableState||((U0=y._readableState)===null||U0===void 0?void 0:U0.readable)!==!1)&&(!y._writableState||y._readableState))}function M(y){var i;return!!(y&&typeof y.write==="function"&&typeof y.on==="function"&&(!y._readableState||((i=y._writableState)===null||i===void 0?void 0:i.writable)!==!1))}function k(y){return!!(y&&typeof y.pipe==="function"&&y._readableState&&typeof y.on==="function"&&typeof y.write==="function")}function f(y){return y&&(y._readableState||y._writableState||typeof y.write==="function"&&typeof y.on==="function"||typeof y.pipe==="function"&&typeof y.on==="function")}function L(y){return!!(y&&!f(y)&&typeof y.pipeThrough==="function"&&typeof y.getReader==="function"&&typeof y.cancel==="function")}function D(y){return!!(y&&!f(y)&&typeof y.getWriter==="function"&&typeof y.abort==="function")}function z(y){return!!(y&&!f(y)&&typeof y.readable==="object"&&typeof y.writable==="object")}function N(y){return L(y)||D(y)||z(y)}function H(y,i){if(y==null)return!1;if(i===!0)return typeof y[Q]==="function";if(i===!1)return typeof y[K]==="function";return typeof y[Q]==="function"||typeof y[K]==="function"}function v(y){if(!f(y))return null;let{_writableState:i,_readableState:U0}=y,m=i||U0;return!!(y.destroyed||y[Z]||m!==null&&m!==void 0&&m.destroyed)}function j(y){if(!M(y))return null;if(y.writableEnded===!0)return!0;let i=y._writableState;if(i!==null&&i!==void 0&&i.errored)return!1;if(typeof(i===null||i===void 0?void 0:i.ended)!=="boolean")return null;return i.ended}function n(y,i){if(!M(y))return null;if(y.writableFinished===!0)return!0;let U0=y._writableState;if(U0!==null&&U0!==void 0&&U0.errored)return!1;if(typeof(U0===null||U0===void 0?void 0:U0.finished)!=="boolean")return null;return!!(U0.finished||i===!1&&U0.ended===!0&&U0.length===0)}function d(y){if(!F(y))return null;if(y.readableEnded===!0)return!0;let i=y._readableState;if(!i||i.errored)return!1;if(typeof(i===null||i===void 0?void 0:i.ended)!=="boolean")return null;return i.ended}function _(y,i){if(!F(y))return null;let U0=y._readableState;if(U0!==null&&U0!==void 0&&U0.errored)return!1;if(typeof(U0===null||U0===void 0?void 0:U0.endEmitted)!=="boolean")return null;return!!(U0.endEmitted||i===!1&&U0.ended===!0&&U0.length===0)}function X(y){if(y&&y[W]!=null)return y[W];if(typeof(y===null||y===void 0?void 0:y.readable)!=="boolean")return null;if(v(y))return!1;return F(y)&&y.readable&&!_(y)}function P(y){if(y&&y[B]!=null)return y[B];if(typeof(y===null||y===void 0?void 0:y.writable)!=="boolean")return null;if(v(y))return!1;return M(y)&&y.writable&&!j(y)}function g(y,i){if(!f(y))return null;if(v(y))return!0;if((i===null||i===void 0?void 0:i.readable)!==!1&&X(y))return!1;if((i===null||i===void 0?void 0:i.writable)!==!1&&P(y))return!1;return!0}function c(y){var i,U0;if(!f(y))return null;if(y.writableErrored)return y.writableErrored;return(i=(U0=y._writableState)===null||U0===void 0?void 0:U0.errored)!==null&&i!==void 0?i:null}function h(y){var i,U0;if(!f(y))return null;if(y.readableErrored)return y.readableErrored;return(i=(U0=y._readableState)===null||U0===void 0?void 0:U0.errored)!==null&&i!==void 0?i:null}function x(y){if(!f(y))return null;if(typeof y.closed==="boolean")return y.closed;let{_writableState:i,_readableState:U0}=y;if(typeof(i===null||i===void 0?void 0:i.closed)==="boolean"||typeof(U0===null||U0===void 0?void 0:U0.closed)==="boolean")return(i===null||i===void 0?void 0:i.closed)||(U0===null||U0===void 0?void 0:U0.closed);if(typeof y._closed==="boolean"&&l(y))return y._closed;return null}function l(y){return typeof y._closed==="boolean"&&typeof y._defaultKeepAlive==="boolean"&&typeof y._removedConnection==="boolean"&&typeof y._removedContLen==="boolean"}function $0(y){return typeof y._sent100==="boolean"&&l(y)}function Z0(y){var i;return typeof y._consuming==="boolean"&&typeof y._dumped==="boolean"&&((i=y.req)===null||i===void 0?void 0:i.upgradeOrConnect)===void 0}function F0(y){if(!f(y))return null;let{_writableState:i,_readableState:U0}=y,m=i||U0;return!m&&$0(y)||!!(m&&m.autoDestroy&&m.emitClose&&m.closed===!1)}function p(y){var i;return!!(y&&((i=y[V])!==null&&i!==void 0?i:y.readableDidRead||y.readableAborted))}function W0(y){var i,U0,m,V0,w0,S,b,O,E,a;return!!(y&&((i=(U0=(m=(V0=(w0=(S=y[G])!==null&&S!==void 0?S:y.readableErrored)!==null&&w0!==void 0?w0:y.writableErrored)!==null&&V0!==void 0?V0:(b=y._readableState)===null||b===void 0?void 0:b.errorEmitted)!==null&&m!==void 0?m:(O=y._writableState)===null||O===void 0?void 0:O.errorEmitted)!==null&&U0!==void 0?U0:(E=y._readableState)===null||E===void 0?void 0:E.errored)!==null&&i!==void 0?i:(a=y._writableState)===null||a===void 0?void 0:a.errored))}q.exports={isDestroyed:v,kIsDestroyed:Z,isDisturbed:p,kIsDisturbed:V,isErrored:W0,kIsErrored:G,isReadable:X,kIsReadable:W,kIsClosedPromise:U,kControllerErrorFunction:w,kIsWritable:B,isClosed:x,isDuplexNodeStream:k,isFinished:g,isIterable:H,isReadableNodeStream:F,isReadableStream:L,isReadableEnded:d,isReadableFinished:_,isReadableErrored:h,isNodeStream:f,isWebStream:N,isWritable:P,isWritableNodeStream:M,isWritableStream:D,isWritableEnded:j,isWritableFinished:n,isWritableErrored:c,isServerRequest:Z0,isServerResponse:$0,willEmitClose:F0,isTransformStream:z}}),s2=g0(($,q)=>{var Q=D1(),{AbortError:K,codes:J}=a0(),{ERR_INVALID_ARG_TYPE:Z,ERR_STREAM_PREMATURE_CLOSE:G}=J,{kEmptyObject:W,once:B}=e0(),{validateAbortSignal:V,validateFunction:U,validateObject:w,validateBoolean:F}=P6(),{Promise:M,PromisePrototypeThen:k,SymbolDispose:f}=P0(),{isClosed:L,isReadable:D,isReadableNodeStream:z,isReadableStream:N,isReadableFinished:H,isReadableErrored:v,isWritable:j,isWritableNodeStream:n,isWritableStream:d,isWritableFinished:_,isWritableErrored:X,isNodeStream:P,willEmitClose:g,kIsClosedPromise:c}=b2(),h;function x(p){return p.setHeader&&typeof p.abort==="function"}var l=()=>{};function $0(p,W0,y){var i,U0;if(arguments.length===2)y=W0,W0=W;else if(W0==null)W0=W;else w(W0,"options");if(U(y,"callback"),V(W0.signal,"options.signal"),y=B(y),N(p)||d(p))return Z0(p,W0,y);if(!P(p))throw new Z("stream",["ReadableStream","WritableStream","Stream"],p);let m=(i=W0.readable)!==null&&i!==void 0?i:z(p),V0=(U0=W0.writable)!==null&&U0!==void 0?U0:n(p),w0=p._writableState,S=p._readableState,b=()=>{if(!p.writable)a()},O=g(p)&&z(p)===m&&n(p)===V0,E=_(p,!1),a=()=>{if(E=!0,p.destroyed)O=!1;if(O&&(!p.readable||m))return;if(!m||K0)y.call(p)},K0=H(p,!1),R=()=>{if(K0=!0,p.destroyed)O=!1;if(O&&(!p.writable||V0))return;if(!V0||E)y.call(p)},Y=(T)=>{y.call(p,T)},C=L(p),u=()=>{C=!0;let T=X(p)||v(p);if(T&&typeof T!=="boolean")return y.call(p,T);if(m&&!K0&&z(p,!0)){if(!H(p,!1))return y.call(p,new G)}if(V0&&!E){if(!_(p,!1))return y.call(p,new G)}y.call(p)},e=()=>{C=!0;let T=X(p)||v(p);if(T&&typeof T!=="boolean")return y.call(p,T);y.call(p)},r=()=>{p.req.on("finish",a)};if(x(p)){if(p.on("complete",a),!O)p.on("abort",u);if(p.req)r();else p.on("request",r)}else if(V0&&!w0)p.on("end",b),p.on("close",b);if(!O&&typeof p.aborted==="boolean")p.on("aborted",u);if(p.on("end",R),p.on("finish",a),W0.error!==!1)p.on("error",Y);if(p.on("close",u),C)Q.nextTick(u);else if(w0!==null&&w0!==void 0&&w0.errorEmitted||S!==null&&S!==void 0&&S.errorEmitted){if(!O)Q.nextTick(e)}else if(!m&&(!O||D(p))&&(E||j(p)===!1))Q.nextTick(e);else if(!V0&&(!O||j(p))&&(K0||D(p)===!1))Q.nextTick(e);else if(S&&p.req&&p.aborted)Q.nextTick(e);let s=()=>{if(y=l,p.removeListener("aborted",u),p.removeListener("complete",a),p.removeListener("abort",u),p.removeListener("request",r),p.req)p.req.removeListener("finish",a);p.removeListener("end",b),p.removeListener("close",b),p.removeListener("finish",a),p.removeListener("end",R),p.removeListener("error",Y),p.removeListener("close",u)};if(W0.signal&&!C){let T=()=>{let t=y;s(),t.call(p,new K(void 0,{cause:W0.signal.reason}))};if(W0.signal.aborted)Q.nextTick(T);else{h=h||e0().addAbortListener;let t=h(W0.signal,T),G0=y;y=B((...Q0)=>{t[f](),G0.apply(p,Q0)})}}return s}function Z0(p,W0,y){let i=!1,U0=l;if(W0.signal)if(U0=()=>{i=!0,y.call(p,new K(void 0,{cause:W0.signal.reason}))},W0.signal.aborted)Q.nextTick(U0);else{h=h||e0().addAbortListener;let V0=h(W0.signal,U0),w0=y;y=B((...S)=>{V0[f](),w0.apply(p,S)})}let m=(...V0)=>{if(!i)Q.nextTick(()=>y.apply(p,V0))};return k(p[c].promise,m,m),l}function F0(p,W0){var y;let i=!1;if(W0===null)W0=W;if((y=W0)!==null&&y!==void 0&&y.cleanup)F(W0.cleanup,"cleanup"),i=W0.cleanup;return new M((U0,m)=>{let V0=$0(p,W0,(w0)=>{if(i)V0();if(w0)m(w0);else U0()})})}q.exports=$0,q.exports.finished=F0}),o1=g0(($,q)=>{var Q=D1(),{aggregateTwoErrors:K,codes:{ERR_MULTIPLE_CALLBACK:J},AbortError:Z}=a0(),{Symbol:G}=P0(),{kIsDestroyed:W,isDestroyed:B,isFinished:V,isServerRequest:U}=b2(),w=G("kDestroy"),F=G("kConstruct");function M(g,c,h){if(g){if(g.stack,c&&!c.errored)c.errored=g;if(h&&!h.errored)h.errored=g}}function k(g,c){let h=this._readableState,x=this._writableState,l=x||h;if(x!==null&&x!==void 0&&x.destroyed||h!==null&&h!==void 0&&h.destroyed){if(typeof c==="function")c();return this}if(M(g,x,h),x)x.destroyed=!0;if(h)h.destroyed=!0;if(!l.constructed)this.once(w,function($0){f(this,K($0,g),c)});else f(this,g,c);return this}function f(g,c,h){let x=!1;function l($0){if(x)return;x=!0;let{_readableState:Z0,_writableState:F0}=g;if(M($0,F0,Z0),F0)F0.closed=!0;if(Z0)Z0.closed=!0;if(typeof h==="function")h($0);if($0)Q.nextTick(L,g,$0);else Q.nextTick(D,g)}try{g._destroy(c||null,l)}catch($0){l($0)}}function L(g,c){z(g,c),D(g)}function D(g){let{_readableState:c,_writableState:h}=g;if(h)h.closeEmitted=!0;if(c)c.closeEmitted=!0;if(h!==null&&h!==void 0&&h.emitClose||c!==null&&c!==void 0&&c.emitClose)g.emit("close")}function z(g,c){let{_readableState:h,_writableState:x}=g;if(x!==null&&x!==void 0&&x.errorEmitted||h!==null&&h!==void 0&&h.errorEmitted)return;if(x)x.errorEmitted=!0;if(h)h.errorEmitted=!0;g.emit("error",c)}function N(){let g=this._readableState,c=this._writableState;if(g)g.constructed=!0,g.closed=!1,g.closeEmitted=!1,g.destroyed=!1,g.errored=null,g.errorEmitted=!1,g.reading=!1,g.ended=g.readable===!1,g.endEmitted=g.readable===!1;if(c)c.constructed=!0,c.destroyed=!1,c.closed=!1,c.closeEmitted=!1,c.errored=null,c.errorEmitted=!1,c.finalCalled=!1,c.prefinished=!1,c.ended=c.writable===!1,c.ending=c.writable===!1,c.finished=c.writable===!1}function H(g,c,h){let{_readableState:x,_writableState:l}=g;if(l!==null&&l!==void 0&&l.destroyed||x!==null&&x!==void 0&&x.destroyed)return this;if(x!==null&&x!==void 0&&x.autoDestroy||l!==null&&l!==void 0&&l.autoDestroy)g.destroy(c);else if(c){if(c.stack,l&&!l.errored)l.errored=c;if(x&&!x.errored)x.errored=c;if(h)Q.nextTick(z,g,c);else z(g,c)}}function v(g,c){if(typeof g._construct!=="function")return;let{_readableState:h,_writableState:x}=g;if(h)h.constructed=!1;if(x)x.constructed=!1;if(g.once(F,c),g.listenerCount(F)>1)return;Q.nextTick(j,g)}function j(g){let c=!1;function h(x){if(c){H(g,x!==null&&x!==void 0?x:new J);return}c=!0;let{_readableState:l,_writableState:$0}=g,Z0=$0||l;if(l)l.constructed=!0;if($0)$0.constructed=!0;if(Z0.destroyed)g.emit(w,x);else if(x)H(g,x,!0);else Q.nextTick(n,g)}try{g._construct((x)=>{Q.nextTick(h,x)})}catch(x){Q.nextTick(h,x)}}function n(g){g.emit(F)}function d(g){return(g===null||g===void 0?void 0:g.setHeader)&&typeof g.abort==="function"}function _(g){g.emit("close")}function X(g,c){g.emit("error",c),Q.nextTick(_,g)}function P(g,c){if(!g||B(g))return;if(!c&&!V(g))c=new Z;if(U(g))g.socket=null,g.destroy(c);else if(d(g))g.abort();else if(d(g.req))g.req.abort();else if(typeof g.destroy==="function")g.destroy(c);else if(typeof g.close==="function")g.close();else if(c)Q.nextTick(X,g,c);else Q.nextTick(_,g);if(!g.destroyed)g[W]=!0}q.exports={construct:v,destroyer:P,destroy:k,undestroy:N,errorOrDestroy:H}}),c5=g0(($,q)=>{var{ArrayIsArray:Q,ObjectSetPrototypeOf:K}=P0(),{EventEmitter:J}=(i1(),X0(p1));function Z(W){J.call(this,W)}K(Z.prototype,J.prototype),K(Z,J),Z.prototype.pipe=function(W,B){let V=this;function U(D){if(W.writable&&W.write(D)===!1&&V.pause)V.pause()}V.on("data",U);function w(){if(V.readable&&V.resume)V.resume()}if(W.on("drain",w),!W._isStdio&&(!B||B.end!==!1))V.on("end",M),V.on("close",k);let F=!1;function M(){if(F)return;F=!0,W.end()}function k(){if(F)return;if(F=!0,typeof W.destroy==="function")W.destroy()}function f(D){if(L(),J.listenerCount(this,"error")===0)this.emit("error",D)}G(V,"error",f),G(W,"error",f);function L(){V.removeListener("data",U),W.removeListener("drain",w),V.removeListener("end",M),V.removeListener("close",k),V.removeListener("error",f),W.removeListener("error",f),V.removeListener("end",L),V.removeListener("close",L),W.removeListener("close",L)}return V.on("end",L),V.on("close",L),W.on("close",L),W.emit("pipe",V),W};function G(W,B,V){if(typeof W.prependListener==="function")return W.prependListener(B,V);if(!W._events||!W._events[B])W.on(B,V);else if(Q(W._events[B]))W._events[B].unshift(V);else W._events[B]=[V,W._events[B]]}q.exports={Stream:Z,prependListener:G}}),L8=g0(($,q)=>{var{SymbolDispose:Q}=P0(),{AbortError:K,codes:J}=a0(),{isNodeStream:Z,isWebStream:G,kControllerErrorFunction:W}=b2(),B=s2(),{ERR_INVALID_ARG_TYPE:V}=J,U,w=(F,M)=>{if(typeof F!=="object"||!("aborted"in F))throw new V(M,"AbortSignal",F)};q.exports.addAbortSignal=function(F,M){if(w(F,"signal"),!Z(M)&&!G(M))throw new V("stream",["ReadableStream","WritableStream","Stream"],M);return q.exports.addAbortSignalNoValidate(F,M)},q.exports.addAbortSignalNoValidate=function(F,M){if(typeof F!=="object"||!("aborted"in F))return M;let k=Z(M)?()=>{M.destroy(new K(void 0,{cause:F.reason}))}:()=>{M[W](new K(void 0,{cause:F.reason}))};if(F.aborted)k();else{U=U||e0().addAbortListener;let f=U(F,k);B(M,f[Q])}return M}}),gV=g0(($,q)=>{var{StringPrototypeSlice:Q,SymbolIterator:K,TypedArrayPrototypeSet:J,Uint8Array:Z}=P0(),{Buffer:G}=(t0(),X0(K2)),{inspect:W}=e0();q.exports=class{constructor(){this.head=null,this.tail=null,this.length=0}push(B){let V={data:B,next:null};if(this.length>0)this.tail.next=V;else this.head=V;this.tail=V,++this.length}unshift(B){let V={data:B,next:this.head};if(this.length===0)this.tail=V;this.head=V,++this.length}shift(){if(this.length===0)return;let B=this.head.data;if(this.length===1)this.head=this.tail=null;else this.head=this.head.next;return--this.length,B}clear(){this.head=this.tail=null,this.length=0}join(B){if(this.length===0)return"";let V=this.head,U=""+V.data;while((V=V.next)!==null)U+=B+V.data;return U}concat(B){if(this.length===0)return G.alloc(0);let V=G.allocUnsafe(B>>>0),U=this.head,w=0;while(U)J(V,U.data,w),w+=U.data.length,U=U.next;return V}consume(B,V){let U=this.head.data;if(BF.length)V+=F,B-=F.length;else{if(B===F.length)if(V+=F,++w,U.next)this.head=U.next;else this.head=this.tail=null;else V+=Q(F,0,B),this.head=U,U.data=Q(F,B);break}++w}while((U=U.next)!==null);return this.length-=w,V}_getBuffer(B){let V=G.allocUnsafe(B),U=B,w=this.head,F=0;do{let M=w.data;if(B>M.length)J(V,M,U-B),B-=M.length;else{if(B===M.length)if(J(V,M,U-B),++F,w.next)this.head=w.next;else this.head=this.tail=null;else J(V,new Z(M.buffer,M.byteOffset,B),U-B),this.head=w,w.data=M.slice(B);break}++F}while((w=w.next)!==null);return this.length-=F,V}[Symbol.for("nodejs.util.inspect.custom")](B,V){return W(this,{...V,depth:0,customInspect:!1})}}}),H8=g0(($,q)=>{var{MathFloor:Q,NumberIsInteger:K}=P0(),{validateInteger:J}=P6(),{ERR_INVALID_ARG_VALUE:Z}=a0().codes,G=16384,W=16;function B(F,M,k){return F.highWaterMark!=null?F.highWaterMark:M?F[k]:null}function V(F){return F?W:G}function U(F,M){if(J(M,"value",0),F)W=M;else G=M}function w(F,M,k,f){let L=B(M,f,k);if(L!=null){if(!K(L)||L<0){let D=f?`options.${k}`:"options.highWaterMark";throw new Z(D,L)}return Q(L)}return V(F.objectMode)}q.exports={getHighWaterMark:w,getDefaultHighWaterMark:V,setDefaultHighWaterMark:U}}),AV=g0(($,q)=>{/*! safe-buffer. MIT License. Feross Aboukhadijeh */var Q=(t0(),X0(K2)),K=Q.Buffer;function J(G,W){for(var B in G)W[B]=G[B]}if(K.from&&K.alloc&&K.allocUnsafe&&K.allocUnsafeSlow)q.exports=Q;else J(Q,$),$.Buffer=Z;function Z(G,W,B){return K(G,W,B)}Z.prototype=Object.create(K.prototype),J(K,Z),Z.from=function(G,W,B){if(typeof G==="number")throw TypeError("Argument must not be a number");return K(G,W,B)},Z.alloc=function(G,W,B){if(typeof G!=="number")throw TypeError("Argument must be a number");var V=K(G);if(W!==void 0)if(typeof B==="string")V.fill(W,B);else V.fill(W);else V.fill(0);return V},Z.allocUnsafe=function(G){if(typeof G!=="number")throw TypeError("Argument must be a number");return K(G)},Z.allocUnsafeSlow=function(G){if(typeof G!=="number")throw TypeError("Argument must be a number");return Q.SlowBuffer(G)}}),XV=g0(($)=>{var q=AV().Buffer,Q=q.isEncoding||function(z){switch(z=""+z,z&&z.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function K(z){if(!z)return"utf8";var N;while(!0)switch(z){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return z;default:if(N)return;z=(""+z).toLowerCase(),N=!0}}function J(z){var N=K(z);if(typeof N!=="string"&&(q.isEncoding===Q||!Q(z)))throw Error("Unknown encoding: "+z);return N||z}$.StringDecoder=Z;function Z(z){this.encoding=J(z);var N;switch(this.encoding){case"utf16le":this.text=F,this.end=M,N=4;break;case"utf8":this.fillLast=V,N=4;break;case"base64":this.text=k,this.end=f,N=3;break;default:this.write=L,this.end=D;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=q.allocUnsafe(N)}Z.prototype.write=function(z){if(z.length===0)return"";var N,H;if(this.lastNeed){if(N=this.fillLast(z),N===void 0)return"";H=this.lastNeed,this.lastNeed=0}else H=0;if(H>5===6)return 2;else if(z>>4===14)return 3;else if(z>>3===30)return 4;return z>>6===2?-1:-2}function W(z,N,H){var v=N.length-1;if(v=0){if(j>0)z.lastNeed=j-1;return j}if(--v=0){if(j>0)z.lastNeed=j-2;return j}if(--v=0){if(j>0)if(j===2)j=0;else z.lastNeed=j-3;return j}return 0}function B(z,N,H){if((N[0]&192)!==128)return z.lastNeed=0,"�";if(z.lastNeed>1&&N.length>1){if((N[1]&192)!==128)return z.lastNeed=1,"�";if(z.lastNeed>2&&N.length>2){if((N[2]&192)!==128)return z.lastNeed=2,"�"}}}function V(z){var N=this.lastTotal-this.lastNeed,H=B(this,z,N);if(H!==void 0)return H;if(this.lastNeed<=z.length)return z.copy(this.lastChar,N,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);z.copy(this.lastChar,N,0,z.length),this.lastNeed-=z.length}function U(z,N){var H=W(this,z,N);if(!this.lastNeed)return z.toString("utf8",N);this.lastTotal=H;var v=z.length-(H-this.lastNeed);return z.copy(this.lastChar,0,v),z.toString("utf8",N,v)}function w(z){var N=z&&z.length?this.write(z):"";if(this.lastNeed)return N+"�";return N}function F(z,N){if((z.length-N)%2===0){var H=z.toString("utf16le",N);if(H){var v=H.charCodeAt(H.length-1);if(v>=55296&&v<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=z[z.length-2],this.lastChar[1]=z[z.length-1],H.slice(0,-1)}return H}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=z[z.length-1],z.toString("utf16le",N,z.length-1)}function M(z){var N=z&&z.length?this.write(z):"";if(this.lastNeed){var H=this.lastTotal-this.lastNeed;return N+this.lastChar.toString("utf16le",0,H)}return N}function k(z,N){var H=(z.length-N)%3;if(H===0)return z.toString("base64",N);if(this.lastNeed=3-H,this.lastTotal=3,H===1)this.lastChar[0]=z[z.length-1];else this.lastChar[0]=z[z.length-2],this.lastChar[1]=z[z.length-1];return z.toString("base64",N,z.length-H)}function f(z){var N=z&&z.length?this.write(z):"";if(this.lastNeed)return N+this.lastChar.toString("base64",0,3-this.lastNeed);return N}function L(z){return z.toString(this.encoding)}function D(z){return z&&z.length?this.write(z):""}}),a9=g0(($,q)=>{var Q=D1(),{PromisePrototypeThen:K,SymbolAsyncIterator:J,SymbolIterator:Z}=P0(),{Buffer:G}=(t0(),X0(K2)),{ERR_INVALID_ARG_TYPE:W,ERR_STREAM_NULL_VALUES:B}=a0().codes;function V(U,w,F){let M;if(typeof w==="string"||w instanceof G)return new U({objectMode:!0,...F,read(){this.push(w),this.push(null)}});let k;if(w&&w[J])k=!0,M=w[J]();else if(w&&w[Z])k=!1,M=w[Z]();else throw new W("iterable",["Iterable"],w);let f=new U({objectMode:!0,highWaterMark:1,...F}),L=!1;f._read=function(){if(!L)L=!0,z()},f._destroy=function(N,H){K(D(N),()=>Q.nextTick(H,N),(v)=>Q.nextTick(H,v||N))};async function D(N){let H=N!==void 0&&N!==null,v=typeof M.throw==="function";if(H&&v){let{value:j,done:n}=await M.throw(N);if(await j,n)return}if(typeof M.return==="function"){let{value:j}=await M.return();await j}}async function z(){for(;;){try{let{value:N,done:H}=k?await M.next():M.next();if(H)f.push(null);else{let v=N&&typeof N.then==="function"?await N:N;if(v===null)throw L=!1,new B;else if(f.push(v))continue;else L=!1}}catch(N){f.destroy(N)}break}}return f}q.exports=V}),v8=g0(($,q)=>{var Q=D1(),{ArrayPrototypeIndexOf:K,NumberIsInteger:J,NumberIsNaN:Z,NumberParseInt:G,ObjectDefineProperties:W,ObjectKeys:B,ObjectSetPrototypeOf:V,Promise:U,SafeSet:w,SymbolAsyncDispose:F,SymbolAsyncIterator:M,Symbol:k}=P0();q.exports=Q0,Q0.ReadableState=G0;var{EventEmitter:f}=(i1(),X0(p1)),{Stream:L,prependListener:D}=c5(),{Buffer:z}=(t0(),X0(K2)),{addAbortSignal:N}=L8(),H=s2(),v=e0().debuglog("stream",(I)=>{v=I}),j=gV(),n=o1(),{getHighWaterMark:d,getDefaultHighWaterMark:_}=H8(),{aggregateTwoErrors:X,codes:{ERR_INVALID_ARG_TYPE:P,ERR_METHOD_NOT_IMPLEMENTED:g,ERR_OUT_OF_RANGE:c,ERR_STREAM_PUSH_AFTER_EOF:h,ERR_STREAM_UNSHIFT_AFTER_END_EVENT:x},AbortError:l}=a0(),{validateObject:$0}=P6(),Z0=k("kPaused"),{StringDecoder:F0}=XV(),p=a9();V(Q0.prototype,L.prototype),V(Q0,L);var W0=()=>{},{errorOrDestroy:y}=n,i=1,U0=2,m=4,V0=8,w0=16,S=32,b=64,O=128,E=256,a=512,K0=1024,R=2048,Y=4096,C=8192,u=16384,e=32768,r=65536,s=131072,T=262144;function t(I){return{enumerable:!1,get(){return(this.state&I)!==0},set(A){if(A)this.state|=I;else this.state&=~I}}}W(G0.prototype,{objectMode:t(i),ended:t(U0),endEmitted:t(m),reading:t(V0),constructed:t(w0),sync:t(S),needReadable:t(b),emittedReadable:t(O),readableListening:t(E),resumeScheduled:t(a),errorEmitted:t(K0),emitClose:t(R),autoDestroy:t(Y),destroyed:t(C),closed:t(u),closeEmitted:t(e),multiAwaitDrain:t(r),readingMore:t(s),dataEmitted:t(T)});function G0(I,A,J0){if(typeof J0!=="boolean")J0=A instanceof c2();if(this.state=R|Y|w0|S,I&&I.objectMode)this.state|=i;if(J0&&I&&I.readableObjectMode)this.state|=i;if(this.highWaterMark=I?d(this,I,"readableHighWaterMark",J0):_(!1),this.buffer=new j,this.length=0,this.pipes=[],this.flowing=null,this[Z0]=null,I&&I.emitClose===!1)this.state&=~R;if(I&&I.autoDestroy===!1)this.state&=~Y;if(this.errored=null,this.defaultEncoding=I&&I.defaultEncoding||"utf8",this.awaitDrainWriters=null,this.decoder=null,this.encoding=null,I&&I.encoding)this.decoder=new F0(I.encoding),this.encoding=I.encoding}function Q0(I){if(!(this instanceof Q0))return new Q0(I);let A=this instanceof c2();if(this._readableState=new G0(I,this,A),I){if(typeof I.read==="function")this._read=I.read;if(typeof I.destroy==="function")this._destroy=I.destroy;if(typeof I.construct==="function")this._construct=I.construct;if(I.signal&&!A)N(I.signal,this)}L.call(this,I),n.construct(this,()=>{if(this._readableState.needReadable)_1(this,this._readableState)})}Q0.prototype.destroy=n.destroy,Q0.prototype._undestroy=n.undestroy,Q0.prototype._destroy=function(I,A){A(I)},Q0.prototype[f.captureRejectionSymbol]=function(I){this.destroy(I)},Q0.prototype[F]=function(){let I;if(!this.destroyed)I=this.readableEnded?null:new l,this.destroy(I);return new U((A,J0)=>H(this,(B0)=>B0&&B0!==I?J0(B0):A(null)))},Q0.prototype.push=function(I,A){return M0(this,I,A,!1)},Q0.prototype.unshift=function(I,A){return M0(this,I,A,!0)};function M0(I,A,J0,B0){v("readableAddChunk",A);let z0=I._readableState,i0;if((z0.state&i)===0){if(typeof A==="string"){if(J0=J0||z0.defaultEncoding,z0.encoding!==J0)if(B0&&z0.encoding)A=z.from(A,J0).toString(z0.encoding);else A=z.from(A,J0),J0=""}else if(A instanceof z)J0="";else if(L._isUint8Array(A))A=L._uint8ArrayToBuffer(A),J0="";else if(A!=null)i0=new P("chunk",["string","Buffer","Uint8Array"],A)}if(i0)y(I,i0);else if(A===null)z0.state&=~V0,O0(I,z0);else if((z0.state&i)!==0||A&&A.length>0)if(B0)if((z0.state&m)!==0)y(I,new x);else if(z0.destroyed||z0.errored)return!1;else I0(I,z0,A,!0);else if(z0.ended)y(I,new h);else if(z0.destroyed||z0.errored)return!1;else if(z0.state&=~V0,z0.decoder&&!J0)if(A=z0.decoder.write(A),z0.objectMode||A.length!==0)I0(I,z0,A,!1);else _1(I,z0);else I0(I,z0,A,!1);else if(!B0)z0.state&=~V0,_1(I,z0);return!z0.ended&&(z0.length0){if((A.state&r)!==0)A.awaitDrainWriters.clear();else A.awaitDrainWriters=null;A.dataEmitted=!0,I.emit("data",J0)}else{if(A.length+=A.objectMode?1:J0.length,B0)A.buffer.unshift(J0);else A.buffer.push(J0);if((A.state&b)!==0)u0(I)}_1(I,A)}Q0.prototype.isPaused=function(){let I=this._readableState;return I[Z0]===!0||I.flowing===!1},Q0.prototype.setEncoding=function(I){let A=new F0(I);this._readableState.decoder=A,this._readableState.encoding=this._readableState.decoder.encoding;let J0=this._readableState.buffer,B0="";for(let z0 of J0)B0+=A.write(z0);if(J0.clear(),B0!=="")J0.push(B0);return this._readableState.length=B0.length,this};var m0=1073741824;function p0(I){if(I>m0)throw new c("size","<= 1GiB",I);else I--,I|=I>>>1,I|=I>>>2,I|=I>>>4,I|=I>>>8,I|=I>>>16,I++;return I}function q2(I,A){if(I<=0||A.length===0&&A.ended)return 0;if((A.state&i)!==0)return 1;if(Z(I)){if(A.flowing&&A.length)return A.buffer.first().length;return A.length}if(I<=A.length)return I;return A.ended?A.length:0}Q0.prototype.read=function(I){if(v("read",I),I===void 0)I=NaN;else if(!J(I))I=G(I,10);let A=this._readableState,J0=I;if(I>A.highWaterMark)A.highWaterMark=p0(I);if(I!==0)A.state&=~O;if(I===0&&A.needReadable&&((A.highWaterMark!==0?A.length>=A.highWaterMark:A.length>0)||A.ended)){if(v("read: emitReadable",A.length,A.ended),A.length===0&&A.ended)v5(this);else u0(this);return null}if(I=q2(I,A),I===0&&A.ended){if(A.length===0)v5(this);return null}let B0=(A.state&b)!==0;if(v("need readable",B0),A.length===0||A.length-I0)z0=a7(I,A);else z0=null;if(z0===null)A.needReadable=A.length<=A.highWaterMark,I=0;else if(A.length-=I,A.multiAwaitDrain)A.awaitDrainWriters.clear();else A.awaitDrainWriters=null;if(A.length===0){if(!A.ended)A.needReadable=!0;if(J0!==I&&A.ended)v5(this)}if(z0!==null&&!A.errorEmitted&&!A.closeEmitted)A.dataEmitted=!0,this.emit("data",z0);return z0};function O0(I,A){if(v("onEofChunk"),A.ended)return;if(A.decoder){let J0=A.decoder.end();if(J0&&J0.length)A.buffer.push(J0),A.length+=A.objectMode?1:J0.length}if(A.ended=!0,A.sync)u0(I);else A.needReadable=!1,A.emittedReadable=!0,E1(I)}function u0(I){let A=I._readableState;if(v("emitReadable",A.needReadable,A.emittedReadable),A.needReadable=!1,!A.emittedReadable)v("emitReadable",A.flowing),A.emittedReadable=!0,Q.nextTick(E1,I)}function E1(I){let A=I._readableState;if(v("emitReadable_",A.destroyed,A.length,A.ended),!A.destroyed&&!A.errored&&(A.length||A.ended))I.emit("readable"),A.emittedReadable=!1;A.needReadable=!A.flowing&&!A.ended&&A.length<=A.highWaterMark,i7(I)}function _1(I,A){if(!A.readingMore&&A.constructed)A.readingMore=!0,Q.nextTick(R2,I,A)}function R2(I,A){while(!A.reading&&!A.ended&&(A.length1&&B0.pipes.includes(I))v("false write response, pause",B0.awaitDrainWriters.size),B0.awaitDrainWriters.add(I);J0.pause()}if(!z1)z1=wJ(J0,I),I.on("drain",z1)}J0.on("data",t7);function t7(F1){v("ondata");let u2=I.write(F1);if(v("dest.write",u2),u2===!1)s7()}function R5(F1){if(v("onerror",F1),A6(),I.removeListener("error",R5),I.listenerCount("error")===0){let u2=I._writableState||I._readableState;if(u2&&!u2.errorEmitted)y(I,F1);else I.emit("error",F1)}}D(I,"error",R5);function I5(){I.removeListener("finish",C5),A6()}I.once("close",I5);function C5(){v("onfinish"),I.removeListener("close",I5),A6()}I.once("finish",C5);function A6(){v("unpipe"),J0.unpipe(I)}if(I.emit("pipe",J0),I.writableNeedDrain===!0)s7();else if(!B0.flowing)v("pipe resume"),J0.resume();return I};function wJ(I,A){return function(){let J0=I._readableState;if(J0.awaitDrainWriters===A)v("pipeOnDrain",1),J0.awaitDrainWriters=null;else if(J0.multiAwaitDrain)v("pipeOnDrain",J0.awaitDrainWriters.size),J0.awaitDrainWriters.delete(A);if((!J0.awaitDrainWriters||J0.awaitDrainWriters.size===0)&&I.listenerCount("data"))I.resume()}}Q0.prototype.unpipe=function(I){let A=this._readableState,J0={hasUnpiped:!1};if(A.pipes.length===0)return this;if(!I){let z0=A.pipes;A.pipes=[],this.pause();for(let i0=0;i00,B0.flowing!==!1)this.resume()}else if(I==="readable"){if(!B0.endEmitted&&!B0.readableListening){if(B0.readableListening=B0.needReadable=!0,B0.flowing=!1,B0.emittedReadable=!1,v("on readable",B0.length,B0.reading),B0.length)u0(this);else if(!B0.reading)Q.nextTick(NJ,this)}}return J0},Q0.prototype.addListener=Q0.prototype.on,Q0.prototype.removeListener=function(I,A){let J0=L.prototype.removeListener.call(this,I,A);if(I==="readable")Q.nextTick(p7,this);return J0},Q0.prototype.off=Q0.prototype.removeListener,Q0.prototype.removeAllListeners=function(I){let A=L.prototype.removeAllListeners.apply(this,arguments);if(I==="readable"||I===void 0)Q.nextTick(p7,this);return A};function p7(I){let A=I._readableState;if(A.readableListening=I.listenerCount("readable")>0,A.resumeScheduled&&A[Z0]===!1)A.flowing=!0;else if(I.listenerCount("data")>0)I.resume();else if(!A.readableListening)A.flowing=null}function NJ(I){v("readable nexttick read 0"),I.read(0)}Q0.prototype.resume=function(){let I=this._readableState;if(!I.flowing)v("resume"),I.flowing=!I.readableListening,YJ(this,I);return I[Z0]=!1,this};function YJ(I,A){if(!A.resumeScheduled)A.resumeScheduled=!0,Q.nextTick(kJ,I,A)}function kJ(I,A){if(v("resume",A.reading),!A.reading)I.read(0);if(A.resumeScheduled=!1,I.emit("resume"),i7(I),A.flowing&&!A.reading)I.read(0)}Q0.prototype.pause=function(){if(v("call pause flowing=%j",this._readableState.flowing),this._readableState.flowing!==!1)v("pause"),this._readableState.flowing=!1,this.emit("pause");return this._readableState[Z0]=!0,this};function i7(I){let A=I._readableState;v("flow",A.flowing);while(A.flowing&&I.read()!==null);}Q0.prototype.wrap=function(I){let A=!1;I.on("data",(B0)=>{if(!this.push(B0)&&I.pause)A=!0,I.pause()}),I.on("end",()=>{this.push(null)}),I.on("error",(B0)=>{y(this,B0)}),I.on("close",()=>{this.destroy()}),I.on("destroy",()=>{this.destroy()}),this._read=()=>{if(A&&I.resume)A=!1,I.resume()};let J0=B(I);for(let B0=1;B0{z0=z2?X(z0,z2):null,J0(),J0=W0});try{while(!0){let z2=I.destroyed?null:I.read();if(z2!==null)yield z2;else if(z0)throw z0;else if(z0===null)return;else await new U(B0)}}catch(z2){throw z0=X(z0,z2),z0}finally{if((z0||(A===null||A===void 0?void 0:A.destroyOnReturn)!==!1)&&(z0===void 0||I._readableState.autoDestroy))n.destroyer(I,null);else I.off("readable",B0),i0()}}W(Q0.prototype,{readable:{__proto__:null,get(){let I=this._readableState;return!!I&&I.readable!==!1&&!I.destroyed&&!I.errorEmitted&&!I.endEmitted},set(I){if(this._readableState)this._readableState.readable=!!I}},readableDidRead:{__proto__:null,enumerable:!1,get:function(){return this._readableState.dataEmitted}},readableAborted:{__proto__:null,enumerable:!1,get:function(){return!!(this._readableState.readable!==!1&&(this._readableState.destroyed||this._readableState.errored)&&!this._readableState.endEmitted)}},readableHighWaterMark:{__proto__:null,enumerable:!1,get:function(){return this._readableState.highWaterMark}},readableBuffer:{__proto__:null,enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}},readableFlowing:{__proto__:null,enumerable:!1,get:function(){return this._readableState.flowing},set:function(I){if(this._readableState)this._readableState.flowing=I}},readableLength:{__proto__:null,enumerable:!1,get(){return this._readableState.length}},readableObjectMode:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.objectMode:!1}},readableEncoding:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.encoding:null}},errored:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.errored:null}},closed:{__proto__:null,get(){return this._readableState?this._readableState.closed:!1}},destroyed:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.destroyed:!1},set(I){if(!this._readableState)return;this._readableState.destroyed=I}},readableEnded:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.endEmitted:!1}}}),W(G0.prototype,{pipesCount:{__proto__:null,get(){return this.pipes.length}},paused:{__proto__:null,get(){return this[Z0]!==!1},set(I){this[Z0]=!!I}}}),Q0._fromList=a7;function a7(I,A){if(A.length===0)return null;let J0;if(A.objectMode)J0=A.buffer.shift();else if(!I||I>=A.length){if(A.decoder)J0=A.buffer.join("");else if(A.buffer.length===1)J0=A.buffer.first();else J0=A.buffer.concat(A.length);A.buffer.clear()}else J0=A.buffer.consume(I,A.decoder);return J0}function v5(I){let A=I._readableState;if(v("endReadable",A.endEmitted),!A.endEmitted)A.ended=!0,Q.nextTick(LJ,A,I)}function LJ(I,A){if(v("endReadableNT",I.endEmitted,I.length),!I.errored&&!I.closeEmitted&&!I.endEmitted&&I.length===0){if(I.endEmitted=!0,A.emit("end"),A.writable&&A.allowHalfOpen===!1)Q.nextTick(HJ,A);else if(I.autoDestroy){let J0=A._writableState;if(!J0||J0.autoDestroy&&(J0.finished||J0.writable===!1))A.destroy()}}}function HJ(I){if(I.writable&&!I.writableEnded&&!I.destroyed)I.end()}Q0.from=function(I,A){return p(Q0,I,A)};var f5;function l7(){if(f5===void 0)f5={};return f5}Q0.fromWeb=function(I,A){return l7().newStreamReadableFromReadableStream(I,A)},Q0.toWeb=function(I,A){return l7().newReadableStreamFromStreamReadable(I,A)},Q0.wrap=function(I,A){var J0,B0;return new Q0({objectMode:(J0=(B0=I.readableObjectMode)!==null&&B0!==void 0?B0:I.objectMode)!==null&&J0!==void 0?J0:!0,...A,destroy(z0,i0){n.destroyer(I,z0),i0(z0)}}).wrap(I)}}),b5=g0(($,q)=>{var Q=D1(),{ArrayPrototypeSlice:K,Error:J,FunctionPrototypeSymbolHasInstance:Z,ObjectDefineProperty:G,ObjectDefineProperties:W,ObjectSetPrototypeOf:B,StringPrototypeToLowerCase:V,Symbol:U,SymbolHasInstance:w}=P0();q.exports=$0,$0.WritableState=x;var{EventEmitter:F}=(i1(),X0(p1)),M=c5().Stream,{Buffer:k}=(t0(),X0(K2)),f=o1(),{addAbortSignal:L}=L8(),{getHighWaterMark:D,getDefaultHighWaterMark:z}=H8(),{ERR_INVALID_ARG_TYPE:N,ERR_METHOD_NOT_IMPLEMENTED:H,ERR_MULTIPLE_CALLBACK:v,ERR_STREAM_CANNOT_PIPE:j,ERR_STREAM_DESTROYED:n,ERR_STREAM_ALREADY_FINISHED:d,ERR_STREAM_NULL_VALUES:_,ERR_STREAM_WRITE_AFTER_END:X,ERR_UNKNOWN_ENCODING:P}=a0().codes,{errorOrDestroy:g}=f;B($0.prototype,M.prototype),B($0,M);function c(){}var h=U("kOnFinished");function x(Y,C,u){if(typeof u!=="boolean")u=C instanceof c2();if(this.objectMode=!!(Y&&Y.objectMode),u)this.objectMode=this.objectMode||!!(Y&&Y.writableObjectMode);this.highWaterMark=Y?D(this,Y,"writableHighWaterMark",u):z(!1),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;let e=!!(Y&&Y.decodeStrings===!1);this.decodeStrings=!e,this.defaultEncoding=Y&&Y.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=y.bind(void 0,C),this.writecb=null,this.writelen=0,this.afterWriteTickInfo=null,l(this),this.pendingcb=0,this.constructed=!0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!Y||Y.emitClose!==!1,this.autoDestroy=!Y||Y.autoDestroy!==!1,this.errored=null,this.closed=!1,this.closeEmitted=!1,this[h]=[]}function l(Y){Y.buffered=[],Y.bufferedIndex=0,Y.allBuffers=!0,Y.allNoop=!0}x.prototype.getBuffer=function(){return K(this.buffered,this.bufferedIndex)},G(x.prototype,"bufferedRequestCount",{__proto__:null,get(){return this.buffered.length-this.bufferedIndex}});function $0(Y){let C=this instanceof c2();if(!C&&!Z($0,this))return new $0(Y);if(this._writableState=new x(Y,this,C),Y){if(typeof Y.write==="function")this._write=Y.write;if(typeof Y.writev==="function")this._writev=Y.writev;if(typeof Y.destroy==="function")this._destroy=Y.destroy;if(typeof Y.final==="function")this._final=Y.final;if(typeof Y.construct==="function")this._construct=Y.construct;if(Y.signal)L(Y.signal,this)}M.call(this,Y),f.construct(this,()=>{let u=this._writableState;if(!u.writing)V0(this,u);O(this,u)})}G($0,w,{__proto__:null,value:function(Y){if(Z(this,Y))return!0;if(this!==$0)return!1;return Y&&Y._writableState instanceof x}}),$0.prototype.pipe=function(){g(this,new j)};function Z0(Y,C,u,e){let r=Y._writableState;if(typeof u==="function")e=u,u=r.defaultEncoding;else{if(!u)u=r.defaultEncoding;else if(u!=="buffer"&&!k.isEncoding(u))throw new P(u);if(typeof e!=="function")e=c}if(C===null)throw new _;else if(!r.objectMode)if(typeof C==="string"){if(r.decodeStrings!==!1)C=k.from(C,u),u="buffer"}else if(C instanceof k)u="buffer";else if(M._isUint8Array(C))C=M._uint8ArrayToBuffer(C),u="buffer";else throw new N("chunk",["string","Buffer","Uint8Array"],C);let s;if(r.ending)s=new X;else if(r.destroyed)s=new n("write");if(s)return Q.nextTick(e,s),g(Y,s,!0),s;return r.pendingcb++,F0(Y,r,C,u,e)}$0.prototype.write=function(Y,C,u){return Z0(this,Y,C,u)===!0},$0.prototype.cork=function(){this._writableState.corked++},$0.prototype.uncork=function(){let Y=this._writableState;if(Y.corked){if(Y.corked--,!Y.writing)V0(this,Y)}},$0.prototype.setDefaultEncoding=function(Y){if(typeof Y==="string")Y=V(Y);if(!k.isEncoding(Y))throw new P(Y);return this._writableState.defaultEncoding=Y,this};function F0(Y,C,u,e,r){let s=C.objectMode?1:u.length;C.length+=s;let T=C.lengthu.bufferedIndex)V0(Y,u);if(e)if(u.afterWriteTickInfo!==null&&u.afterWriteTickInfo.cb===r)u.afterWriteTickInfo.count++;else u.afterWriteTickInfo={count:1,cb:r,stream:Y,state:u},Q.nextTick(i,u.afterWriteTickInfo);else U0(Y,u,1,r)}}function i({stream:Y,state:C,count:u,cb:e}){return C.afterWriteTickInfo=null,U0(Y,C,u,e)}function U0(Y,C,u,e){if(!C.ending&&!Y.destroyed&&C.length===0&&C.needDrain)C.needDrain=!1,Y.emit("drain");while(u-- >0)C.pendingcb--,e();if(C.destroyed)m(C);O(Y,C)}function m(Y){if(Y.writing)return;for(let r=Y.bufferedIndex;r1&&Y._writev){C.pendingcb-=s-1;let t=C.allNoop?c:(Q0)=>{for(let M0=T;M0256)u.splice(0,T),C.bufferedIndex=0;else C.bufferedIndex=T}C.bufferProcessing=!1}$0.prototype._write=function(Y,C,u){if(this._writev)this._writev([{chunk:Y,encoding:C}],u);else throw new H("_write()")},$0.prototype._writev=null,$0.prototype.end=function(Y,C,u){let e=this._writableState;if(typeof Y==="function")u=Y,Y=null,C=null;else if(typeof C==="function")u=C,C=null;let r;if(Y!==null&&Y!==void 0){let s=Z0(this,Y,C);if(s instanceof J)r=s}if(e.corked)e.corked=1,this.uncork();if(r);else if(!e.errored&&!e.ending)e.ending=!0,O(this,e,!0),e.ended=!0;else if(e.finished)r=new d("end");else if(e.destroyed)r=new n("end");if(typeof u==="function")if(r||e.finished)Q.nextTick(u,r);else e[h].push(u);return this};function w0(Y){return Y.ending&&!Y.destroyed&&Y.constructed&&Y.length===0&&!Y.errored&&Y.buffered.length===0&&!Y.finished&&!Y.writing&&!Y.errorEmitted&&!Y.closeEmitted}function S(Y,C){let u=!1;function e(r){if(u){g(Y,r!==null&&r!==void 0?r:v());return}if(u=!0,C.pendingcb--,r){let s=C[h].splice(0);for(let T=0;T{if(w0(r))E(e,r);else r.pendingcb--},Y,C);else if(w0(C))C.pendingcb++,E(Y,C)}}}function E(Y,C){C.pendingcb--,C.finished=!0;let u=C[h].splice(0);for(let e=0;e{var Q=D1(),K=(t0(),X0(K2)),{isReadable:J,isWritable:Z,isIterable:G,isNodeStream:W,isReadableNodeStream:B,isWritableNodeStream:V,isDuplexNodeStream:U,isReadableStream:w,isWritableStream:F}=b2(),M=s2(),{AbortError:k,codes:{ERR_INVALID_ARG_TYPE:f,ERR_INVALID_RETURN_VALUE:L}}=a0(),{destroyer:D}=o1(),z=c2(),N=v8(),H=b5(),{createDeferredPromise:v}=e0(),j=a9(),n=globalThis.Blob||K.Blob,d=typeof n<"u"?function(h){return h instanceof n}:function(h){return!1},_=globalThis.AbortController||O6().AbortController,{FunctionPrototypeCall:X}=P0();class P extends z{constructor(h){super(h);if((h===null||h===void 0?void 0:h.readable)===!1)this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0;if((h===null||h===void 0?void 0:h.writable)===!1)this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0}}q.exports=function h(x,l){if(U(x))return x;if(B(x))return c({readable:x});if(V(x))return c({writable:x});if(W(x))return c({writable:!1,readable:!1});if(w(x))return c({readable:N.fromWeb(x)});if(F(x))return c({writable:H.fromWeb(x)});if(typeof x==="function"){let{value:Z0,write:F0,final:p,destroy:W0}=g(x);if(G(Z0))return j(P,Z0,{objectMode:!0,write:F0,final:p,destroy:W0});let y=Z0===null||Z0===void 0?void 0:Z0.then;if(typeof y==="function"){let i,U0=X(y,Z0,(m)=>{if(m!=null)throw new L("nully","body",m)},(m)=>{D(i,m)});return i=new P({objectMode:!0,readable:!1,write:F0,final(m){p(async()=>{try{await U0,Q.nextTick(m,null)}catch(V0){Q.nextTick(m,V0)}})},destroy:W0})}throw new L("Iterable, AsyncIterable or AsyncFunction",l,Z0)}if(d(x))return h(x.arrayBuffer());if(G(x))return j(P,x,{objectMode:!0,writable:!1});if(w(x===null||x===void 0?void 0:x.readable)&&F(x===null||x===void 0?void 0:x.writable))return P.fromWeb(x);if(typeof(x===null||x===void 0?void 0:x.writable)==="object"||typeof(x===null||x===void 0?void 0:x.readable)==="object"){let Z0=x!==null&&x!==void 0&&x.readable?B(x===null||x===void 0?void 0:x.readable)?x===null||x===void 0?void 0:x.readable:h(x.readable):void 0,F0=x!==null&&x!==void 0&&x.writable?V(x===null||x===void 0?void 0:x.writable)?x===null||x===void 0?void 0:x.writable:h(x.writable):void 0;return c({readable:Z0,writable:F0})}let $0=x===null||x===void 0?void 0:x.then;if(typeof $0==="function"){let Z0;return X($0,x,(F0)=>{if(F0!=null)Z0.push(F0);Z0.push(null)},(F0)=>{D(Z0,F0)}),Z0=new P({objectMode:!0,writable:!1,read(){}})}throw new f(l,["Blob","ReadableStream","WritableStream","Stream","Iterable","AsyncIterable","Function","{ readable, writable } pair","Promise"],x)};function g(h){let{promise:x,resolve:l}=v(),$0=new _,Z0=$0.signal;return{value:h(async function*(){while(!0){let F0=x;x=null;let{chunk:p,done:W0,cb:y}=await F0;if(Q.nextTick(y),W0)return;if(Z0.aborted)throw new k(void 0,{cause:Z0.reason});({promise:x,resolve:l}=v()),yield p}}(),{signal:Z0}),write(F0,p,W0){let y=l;l=null,y({chunk:F0,done:!1,cb:W0})},final(F0){let p=l;l=null,p({done:!0,cb:F0})},destroy(F0,p){$0.abort(),p(F0)}}}function c(h){let x=h.readable&&typeof h.readable.read!=="function"?N.wrap(h.readable):h.readable,l=h.writable,$0=!!J(x),Z0=!!Z(l),F0,p,W0,y,i;function U0(m){let V0=y;if(y=null,V0)V0(m);else if(m)i.destroy(m)}if(i=new P({readableObjectMode:!!(x!==null&&x!==void 0&&x.readableObjectMode),writableObjectMode:!!(l!==null&&l!==void 0&&l.writableObjectMode),readable:$0,writable:Z0}),Z0)M(l,(m)=>{if(Z0=!1,m)D(x,m);U0(m)}),i._write=function(m,V0,w0){if(l.write(m,V0))w0();else F0=w0},i._final=function(m){l.end(),p=m},l.on("drain",function(){if(F0){let m=F0;F0=null,m()}}),l.on("finish",function(){if(p){let m=p;p=null,m()}});if($0)M(x,(m)=>{if($0=!1,m)D(x,m);U0(m)}),x.on("readable",function(){if(W0){let m=W0;W0=null,m()}}),x.on("end",function(){i.push(null)}),i._read=function(){while(!0){let m=x.read();if(m===null){W0=i._read;return}if(!i.push(m))return}};return i._destroy=function(m,V0){if(!m&&y!==null)m=new k;if(W0=null,F0=null,p=null,y===null)V0(m);else y=V0,D(l,m),D(x,m)},i}}),c2=g0(($,q)=>{var{ObjectDefineProperties:Q,ObjectGetOwnPropertyDescriptor:K,ObjectKeys:J,ObjectSetPrototypeOf:Z}=P0();q.exports=B;var G=v8(),W=b5();Z(B.prototype,G.prototype),Z(B,G);{let F=J(W.prototype);for(let M=0;M{var{ObjectSetPrototypeOf:Q,Symbol:K}=P0();q.exports=B;var{ERR_METHOD_NOT_IMPLEMENTED:J}=a0().codes,Z=c2(),{getHighWaterMark:G}=H8();Q(B.prototype,Z.prototype),Q(B,Z);var W=K("kCallback");function B(w){if(!(this instanceof B))return new B(w);let F=w?G(this,w,"readableHighWaterMark",!0):null;if(F===0)w={...w,highWaterMark:null,readableHighWaterMark:F,writableHighWaterMark:w.writableHighWaterMark||0};if(Z.call(this,w),this._readableState.sync=!1,this[W]=null,w){if(typeof w.transform==="function")this._transform=w.transform;if(typeof w.flush==="function")this._flush=w.flush}this.on("prefinish",U)}function V(w){if(typeof this._flush==="function"&&!this.destroyed)this._flush((F,M)=>{if(F){if(w)w(F);else this.destroy(F);return}if(M!=null)this.push(M);if(this.push(null),w)w()});else if(this.push(null),w)w()}function U(){if(this._final!==V)V.call(this)}B.prototype._final=V,B.prototype._transform=function(w,F,M){throw new J("_transform()")},B.prototype._write=function(w,F,M){let k=this._readableState,f=this._writableState,L=k.length;this._transform(w,F,(D,z)=>{if(D){M(D);return}if(z!=null)this.push(z);if(f.ended||L===k.length||k.length{var{ObjectSetPrototypeOf:Q}=P0();q.exports=J;var K=l9();Q(J.prototype,K.prototype),Q(J,K);function J(Z){if(!(this instanceof J))return new J(Z);K.call(this,Z)}J.prototype._transform=function(Z,G,W){W(null,Z)}}),n5=g0(($,q)=>{var Q=D1(),{ArrayIsArray:K,Promise:J,SymbolAsyncIterator:Z,SymbolDispose:G}=P0(),W=s2(),{once:B}=e0(),V=o1(),U=c2(),{aggregateTwoErrors:w,codes:{ERR_INVALID_ARG_TYPE:F,ERR_INVALID_RETURN_VALUE:M,ERR_MISSING_ARGS:k,ERR_STREAM_DESTROYED:f,ERR_STREAM_PREMATURE_CLOSE:L},AbortError:D}=a0(),{validateFunction:z,validateAbortSignal:N}=P6(),{isIterable:H,isReadable:v,isReadableNodeStream:j,isNodeStream:n,isTransformStream:d,isWebStream:_,isReadableStream:X,isReadableFinished:P}=b2(),g=globalThis.AbortController||O6().AbortController,c,h,x;function l(m,V0,w0){let S=!1;m.on("close",()=>{S=!0});let b=W(m,{readable:V0,writable:w0},(O)=>{S=!O});return{destroy:(O)=>{if(S)return;S=!0,V.destroyer(m,O||new f("pipe"))},cleanup:b}}function $0(m){return z(m[m.length-1],"streams[stream.length - 1]"),m.pop()}function Z0(m){if(H(m))return m;else if(j(m))return F0(m);throw new F("val",["Readable","Iterable","AsyncIterable"],m)}async function*F0(m){if(!h)h=v8();yield*h.prototype[Z].call(m)}async function p(m,V0,w0,{end:S}){let b,O=null,E=(R)=>{if(R)b=R;if(O){let Y=O;O=null,Y()}},a=()=>new J((R,Y)=>{if(b)Y(b);else O=()=>{if(b)Y(b);else R()}});V0.on("drain",E);let K0=W(V0,{readable:!1},E);try{if(V0.writableNeedDrain)await a();for await(let R of m)if(!V0.write(R))await a();if(S)V0.end(),await a();w0()}catch(R){w0(b!==R?w(b,R):R)}finally{K0(),V0.off("drain",E)}}async function W0(m,V0,w0,{end:S}){if(d(V0))V0=V0.writable;let b=V0.getWriter();try{for await(let O of m)await b.ready,b.write(O).catch(()=>{});if(await b.ready,S)await b.close();w0()}catch(O){try{await b.abort(O),w0(O)}catch(E){w0(E)}}}function y(...m){return i(m,B($0(m)))}function i(m,V0,w0){if(m.length===1&&K(m[0]))m=m[0];if(m.length<2)throw new k("streams");let S=new g,b=S.signal,O=w0===null||w0===void 0?void 0:w0.signal,E=[];N(O,"options.signal");function a(){r(new D)}x=x||e0().addAbortListener;let K0;if(O)K0=x(O,a);let R,Y,C=[],u=0;function e(Q0){r(Q0,--u===0)}function r(Q0,M0){var I0;if(Q0&&(!R||R.code==="ERR_STREAM_PREMATURE_CLOSE"))R=Q0;if(!R&&!M0)return;while(C.length)C.shift()(R);if((I0=K0)===null||I0===void 0||I0[G](),S.abort(),M0){if(!R)E.forEach((m0)=>m0());Q.nextTick(V0,R,Y)}}let s;for(let Q0=0;Q00,p0=I0||(w0===null||w0===void 0?void 0:w0.end)!==!1,q2=Q0===m.length-1;if(n(M0)){let O0=function(u0){if(u0&&u0.name!=="AbortError"&&u0.code!=="ERR_STREAM_PREMATURE_CLOSE")e(u0)};var T=O0;if(p0){let{destroy:u0,cleanup:E1}=l(M0,I0,m0);if(C.push(u0),v(M0)&&q2)E.push(E1)}if(M0.on("error",O0),v(M0)&&q2)E.push(()=>{M0.removeListener("error",O0)})}if(Q0===0)if(typeof M0==="function"){if(s=M0({signal:b}),!H(s))throw new M("Iterable, AsyncIterable or Stream","source",s)}else if(H(M0)||j(M0)||d(M0))s=M0;else s=U.from(M0);else if(typeof M0==="function"){if(d(s)){var t;s=Z0((t=s)===null||t===void 0?void 0:t.readable)}else s=Z0(s);if(s=M0(s,{signal:b}),I0){if(!H(s,!0))throw new M("AsyncIterable",`transform[${Q0-1}]`,s)}else{var G0;if(!c)c=r9();let O0=new c({objectMode:!0}),u0=(G0=s)===null||G0===void 0?void 0:G0.then;if(typeof u0==="function")u++,u0.call(s,(R2)=>{if(Y=R2,R2!=null)O0.write(R2);if(p0)O0.end();Q.nextTick(e)},(R2)=>{O0.destroy(R2),Q.nextTick(e,R2)});else if(H(s,!0))u++,p(s,O0,e,{end:p0});else if(X(s)||d(s)){let R2=s.readable||s;u++,p(R2,O0,e,{end:p0})}else throw new M("AsyncIterable or Promise","destination",s);s=O0;let{destroy:E1,cleanup:_1}=l(s,!1,!0);if(C.push(E1),q2)E.push(_1)}}else if(n(M0)){if(j(s)){u+=2;let O0=U0(s,M0,e,{end:p0});if(v(M0)&&q2)E.push(O0)}else if(d(s)||X(s)){let O0=s.readable||s;u++,p(O0,M0,e,{end:p0})}else if(H(s))u++,p(s,M0,e,{end:p0});else throw new F("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],s);s=M0}else if(_(M0)){if(j(s))u++,W0(Z0(s),M0,e,{end:p0});else if(X(s)||H(s))u++,W0(s,M0,e,{end:p0});else if(d(s))u++,W0(s.readable,M0,e,{end:p0});else throw new F("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],s);s=M0}else s=U.from(M0)}if(b!==null&&b!==void 0&&b.aborted||O!==null&&O!==void 0&&O.aborted)Q.nextTick(a);return s}function U0(m,V0,w0,{end:S}){let b=!1;if(V0.on("close",()=>{if(!b)w0(new L)}),m.pipe(V0,{end:!1}),S){let E=function(){b=!0,V0.end()};var O=E;if(P(m))Q.nextTick(E);else m.once("end",E)}else w0();return W(m,{readable:!0,writable:!1},(E)=>{let a=m._readableState;if(E&&E.code==="ERR_STREAM_PREMATURE_CLOSE"&&a&&a.ended&&!a.errored&&!a.errorEmitted)m.once("end",w0).once("error",w0);else w0(E)}),W(V0,{readable:!1,writable:!0},w0)}q.exports={pipelineImpl:i,pipeline:y}}),s9=g0(($,q)=>{var{pipeline:Q}=n5(),K=c2(),{destroyer:J}=o1(),{isNodeStream:Z,isReadable:G,isWritable:W,isWebStream:B,isTransformStream:V,isWritableStream:U,isReadableStream:w}=b2(),{AbortError:F,codes:{ERR_INVALID_ARG_VALUE:M,ERR_MISSING_ARGS:k}}=a0(),f=s2();q.exports=function(...L){if(L.length===0)throw new k("streams");if(L.length===1)return K.from(L[0]);let D=[...L];if(typeof L[0]==="function")L[0]=K.from(L[0]);if(typeof L[L.length-1]==="function"){let g=L.length-1;L[g]=K.from(L[g])}for(let g=0;g0&&!(W(L[g])||U(L[g])||V(L[g])))throw new M(`streams[${g}]`,D[g],"must be writable")}let z,N,H,v,j;function n(g){let c=v;if(v=null,c)c(g);else if(g)j.destroy(g);else if(!P&&!X)j.destroy()}let d=L[0],_=Q(L,n),X=!!(W(d)||U(d)||V(d)),P=!!(G(_)||w(_)||V(_));if(j=new K({writableObjectMode:!!(d!==null&&d!==void 0&&d.writableObjectMode),readableObjectMode:!!(_!==null&&_!==void 0&&_.readableObjectMode),writable:X,readable:P}),X){if(Z(d))j._write=function(c,h,x){if(d.write(c,h))x();else z=x},j._final=function(c){d.end(),N=c},d.on("drain",function(){if(z){let c=z;z=null,c()}});else if(B(d)){let c=(V(d)?d.writable:d).getWriter();j._write=async function(h,x,l){try{await c.ready,c.write(h).catch(()=>{}),l()}catch($0){l($0)}},j._final=async function(h){try{await c.ready,c.close().catch(()=>{}),N=h}catch(x){h(x)}}}let g=V(_)?_.readable:_;f(g,()=>{if(N){let c=N;N=null,c()}})}if(P){if(Z(_))_.on("readable",function(){if(H){let g=H;H=null,g()}}),_.on("end",function(){j.push(null)}),j._read=function(){while(!0){let g=_.read();if(g===null){H=j._read;return}if(!j.push(g))return}};else if(B(_)){let g=(V(_)?_.readable:_).getReader();j._read=async function(){while(!0)try{let{value:c,done:h}=await g.read();if(!j.push(c))return;if(h){j.push(null);return}}catch{return}}}}return j._destroy=function(g,c){if(!g&&v!==null)g=new F;if(H=null,z=null,N=null,v===null)c(g);else if(v=c,Z(_))J(_,g)},j}}),hV=g0(($,q)=>{var Q=globalThis.AbortController||O6().AbortController,{codes:{ERR_INVALID_ARG_VALUE:K,ERR_INVALID_ARG_TYPE:J,ERR_MISSING_ARGS:Z,ERR_OUT_OF_RANGE:G},AbortError:W}=a0(),{validateAbortSignal:B,validateInteger:V,validateObject:U}=P6(),w=P0().Symbol("kWeak"),F=P0().Symbol("kResistStopPropagation"),{finished:M}=s2(),k=s9(),{addAbortSignalNoValidate:f}=L8(),{isWritable:L,isNodeStream:D}=b2(),{deprecate:z}=e0(),{ArrayPrototypePush:N,Boolean:H,MathFloor:v,Number:j,NumberIsNaN:n,Promise:d,PromiseReject:_,PromiseResolve:X,PromisePrototypeThen:P,Symbol:g}=P0(),c=g("kEmpty"),h=g("kEof");function x(O,E){if(E!=null)U(E,"options");if((E===null||E===void 0?void 0:E.signal)!=null)B(E.signal,"options.signal");if(D(O)&&!L(O))throw new K("stream",O,"must be writable");let a=k(this,O);if(E!==null&&E!==void 0&&E.signal)f(E.signal,a);return a}function l(O,E){if(typeof O!=="function")throw new J("fn",["Function","AsyncFunction"],O);if(E!=null)U(E,"options");if((E===null||E===void 0?void 0:E.signal)!=null)B(E.signal,"options.signal");let a=1;if((E===null||E===void 0?void 0:E.concurrency)!=null)a=v(E.concurrency);let K0=a-1;if((E===null||E===void 0?void 0:E.highWaterMark)!=null)K0=v(E.highWaterMark);return V(a,"options.concurrency",1),V(K0,"options.highWaterMark",0),K0+=a,async function*(){let R=e0().AbortSignalAny([E===null||E===void 0?void 0:E.signal].filter(H)),Y=this,C=[],u={signal:R},e,r,s=!1,T=0;function t(){s=!0,G0()}function G0(){T-=1,Q0()}function Q0(){if(r&&!s&&T=K0||T>=a))await new d((m0)=>{r=m0})}C.push(h)}catch(I0){let m0=_(I0);P(m0,G0,t),C.push(m0)}finally{if(s=!0,e)e(),e=null}}M0();try{while(!0){while(C.length>0){let I0=await C[0];if(I0===h)return;if(R.aborted)throw new W;if(I0!==c)yield I0;C.shift(),Q0()}await new d((I0)=>{e=I0})}}finally{if(s=!0,r)r(),r=null}}.call(this)}function $0(O=void 0){if(O!=null)U(O,"options");if((O===null||O===void 0?void 0:O.signal)!=null)B(O.signal,"options.signal");return async function*(){let E=0;for await(let K0 of this){var a;if(O!==null&&O!==void 0&&(a=O.signal)!==null&&a!==void 0&&a.aborted)throw new W({cause:O.signal.reason});yield[E++,K0]}}.call(this)}async function Z0(O,E=void 0){for await(let a of y.call(this,O,E))return!0;return!1}async function F0(O,E=void 0){if(typeof O!=="function")throw new J("fn",["Function","AsyncFunction"],O);return!await Z0.call(this,async(...a)=>{return!await O(...a)},E)}async function p(O,E){for await(let a of y.call(this,O,E))return a;return}async function W0(O,E){if(typeof O!=="function")throw new J("fn",["Function","AsyncFunction"],O);async function a(K0,R){return await O(K0,R),c}for await(let K0 of l.call(this,a,E));}function y(O,E){if(typeof O!=="function")throw new J("fn",["Function","AsyncFunction"],O);async function a(K0,R){if(await O(K0,R))return K0;return c}return l.call(this,a,E)}class i extends Z{constructor(){super("reduce");this.message="Reduce of an empty stream requires an initial value"}}async function U0(O,E,a){var K0;if(typeof O!=="function")throw new J("reducer",["Function","AsyncFunction"],O);if(a!=null)U(a,"options");if((a===null||a===void 0?void 0:a.signal)!=null)B(a.signal,"options.signal");let R=arguments.length>1;if(a!==null&&a!==void 0&&(K0=a.signal)!==null&&K0!==void 0&&K0.aborted){let r=new W(void 0,{cause:a.signal.reason});throw this.once("error",()=>{}),await M(this.destroy(r)),r}let Y=new Q,C=Y.signal;if(a!==null&&a!==void 0&&a.signal){let r={once:!0,[w]:this,[F]:!0};a.signal.addEventListener("abort",()=>Y.abort(),r)}let u=!1;try{for await(let r of this){var e;if(u=!0,a!==null&&a!==void 0&&(e=a.signal)!==null&&e!==void 0&&e.aborted)throw new W;if(!R)E=r,R=!0;else E=await O(E,r,{signal:C})}if(!u&&!R)throw new i}finally{Y.abort()}return E}async function m(O){if(O!=null)U(O,"options");if((O===null||O===void 0?void 0:O.signal)!=null)B(O.signal,"options.signal");let E=[];for await(let K0 of this){var a;if(O!==null&&O!==void 0&&(a=O.signal)!==null&&a!==void 0&&a.aborted)throw new W(void 0,{cause:O.signal.reason});N(E,K0)}return E}function V0(O,E){let a=l.call(this,O,E);return async function*(){for await(let K0 of a)yield*K0}.call(this)}function w0(O){if(O=j(O),n(O))return 0;if(O<0)throw new G("number",">= 0",O);return O}function S(O,E=void 0){if(E!=null)U(E,"options");if((E===null||E===void 0?void 0:E.signal)!=null)B(E.signal,"options.signal");return O=w0(O),async function*(){var a;if(E!==null&&E!==void 0&&(a=E.signal)!==null&&a!==void 0&&a.aborted)throw new W;for await(let R of this){var K0;if(E!==null&&E!==void 0&&(K0=E.signal)!==null&&K0!==void 0&&K0.aborted)throw new W;if(O--<=0)yield R}}.call(this)}function b(O,E=void 0){if(E!=null)U(E,"options");if((E===null||E===void 0?void 0:E.signal)!=null)B(E.signal,"options.signal");return O=w0(O),async function*(){var a;if(E!==null&&E!==void 0&&(a=E.signal)!==null&&a!==void 0&&a.aborted)throw new W;for await(let R of this){var K0;if(E!==null&&E!==void 0&&(K0=E.signal)!==null&&K0!==void 0&&K0.aborted)throw new W;if(O-- >0)yield R;if(O<=0)return}}.call(this)}q.exports.streamReturningOperators={asIndexedPairs:z($0,"readable.asIndexedPairs will be removed in a future version."),drop:S,filter:y,flatMap:V0,map:l,take:b,compose:x},q.exports.promiseReturningOperators={every:F0,forEach:W0,reduce:U0,toArray:m,some:Z0,find:p}}),t9=g0(($,q)=>{var{ArrayPrototypePop:Q,Promise:K}=P0(),{isIterable:J,isNodeStream:Z,isWebStream:G}=b2(),{pipelineImpl:W}=n5(),{finished:B}=s2();e9();function V(...U){return new K((w,F)=>{let M,k,f=U[U.length-1];if(f&&typeof f==="object"&&!Z(f)&&!J(f)&&!G(f)){let L=Q(U);M=L.signal,k=L.end}W(U,(L,D)=>{if(L)F(L);else w(D)},{signal:M,end:k})})}q.exports={finished:B,pipeline:V}}),e9=g0(($,q)=>{var{Buffer:Q}=(t0(),X0(K2)),{ObjectDefineProperty:K,ObjectKeys:J,ReflectApply:Z}=P0(),{promisify:{custom:G}}=e0(),{streamReturningOperators:W,promiseReturningOperators:B}=hV(),{codes:{ERR_ILLEGAL_CONSTRUCTOR:V}}=a0(),U=s9(),{setDefaultHighWaterMark:w,getDefaultHighWaterMark:F}=H8(),{pipeline:M}=n5(),{destroyer:k}=o1(),f=s2(),L=t9(),D=b2(),z=q.exports=c5().Stream;z.isDestroyed=D.isDestroyed,z.isDisturbed=D.isDisturbed,z.isErrored=D.isErrored,z.isReadable=D.isReadable,z.isWritable=D.isWritable,z.Readable=v8();for(let H of J(W)){let v=function(...n){if(new.target)throw V();return z.Readable.from(Z(j,this,n))},j=W[H];K(v,"name",{__proto__:null,value:j.name}),K(v,"length",{__proto__:null,value:j.length}),K(z.Readable.prototype,H,{__proto__:null,value:v,enumerable:!1,configurable:!0,writable:!0})}for(let H of J(B)){let v=function(...n){if(new.target)throw V();return Z(j,this,n)},j=B[H];K(v,"name",{__proto__:null,value:j.name}),K(v,"length",{__proto__:null,value:j.length}),K(z.Readable.prototype,H,{__proto__:null,value:v,enumerable:!1,configurable:!0,writable:!0})}z.Writable=b5(),z.Duplex=c2(),z.Transform=l9(),z.PassThrough=r9(),z.pipeline=M;var{addAbortSignal:N}=L8();z.addAbortSignal=N,z.finished=f,z.destroy=k,z.compose=U,z.setDefaultHighWaterMark=w,z.getDefaultHighWaterMark=F,K(z,"promises",{__proto__:null,configurable:!0,enumerable:!0,get(){return L}}),K(M,G,{__proto__:null,enumerable:!0,get(){return L.pipeline}}),K(f,G,{__proto__:null,enumerable:!0,get(){return L.finished}}),z.Stream=z,z._isUint8Array=function(H){return H instanceof Uint8Array},z._uint8ArrayToBuffer=function(H){return Q.from(H.buffer,H.byteOffset,H.byteLength)}}),xV=g0(($,q)=>{var Q=a1();{let K=e9(),J=t9(),Z=K.Readable.destroy;q.exports=K.Readable,q.exports._uint8ArrayToBuffer=K._uint8ArrayToBuffer,q.exports._isUint8Array=K._isUint8Array,q.exports.isDisturbed=K.isDisturbed,q.exports.isErrored=K.isErrored,q.exports.isReadable=K.isReadable,q.exports.Readable=K.Readable,q.exports.Writable=K.Writable,q.exports.Duplex=K.Duplex,q.exports.Transform=K.Transform,q.exports.PassThrough=K.PassThrough,q.exports.addAbortSignal=K.addAbortSignal,q.exports.finished=K.finished,q.exports.destroy=K.destroy,q.exports.destroy=Z,q.exports.pipeline=K.pipeline,q.exports.compose=K.compose,Object.defineProperty(K,"promises",{configurable:!0,enumerable:!0,get(){return J}}),q.exports.Stream=K.Stream}q.exports.default=q.exports});$$.exports=xV()});var d5=N0((Dz,Q$)=>{Q$.exports=a1()});var n2=N0((J2)=>{J2.base64=!0;J2.array=!0;J2.string=!0;J2.arraybuffer=typeof ArrayBuffer<"u"&&typeof Uint8Array<"u";J2.nodebuffer=typeof Buffer<"u";J2.uint8array=typeof Uint8Array<"u";if(typeof ArrayBuffer>"u")J2.blob=!1;else{f8=new ArrayBuffer(0);try{J2.blob=new Blob([f8],{type:"application/zip"}).size===0}catch($){try{m5=self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder,R8=new m5,R8.append(f8),J2.blob=R8.getBlob("application/zip").size===0}catch(q){J2.blob=!1}}}var f8,m5,R8;try{J2.nodestream=!!d5().Readable}catch($){J2.nodestream=!1}});var i5=N0((p5)=>{var OV=T0(),PV=n2(),A2="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";p5.encode=function($){var q=[],Q,K,J,Z,G,W,B,V=0,U=$.length,w=U,F=OV.getTypeOf($)!=="string";while(V<$.length){if(w=U-V,!F)Q=$.charCodeAt(V++),K=V>2,G=(Q&3)<<4|K>>4,W=w>1?(K&15)<<2|J>>6:64,B=w>2?J&63:64,q.push(A2.charAt(Z)+A2.charAt(G)+A2.charAt(W)+A2.charAt(B))}return q.join("")};p5.decode=function($){var q,Q,K,J,Z,G,W,B=0,V=0,U="data:";if($.substr(0,U.length)===U)throw Error("Invalid base64 input, it looks like a data url.");$=$.replace(/[^A-Za-z0-9+/=]/g,"");var w=$.length*3/4;if($.charAt($.length-1)===A2.charAt(64))w--;if($.charAt($.length-2)===A2.charAt(64))w--;if(w%1!==0)throw Error("Invalid base64 input, bad content length.");var F;if(PV.uint8array)F=new Uint8Array(w|0);else F=Array(w|0);while(B<$.length){if(J=A2.indexOf($.charAt(B++)),Z=A2.indexOf($.charAt(B++)),G=A2.indexOf($.charAt(B++)),W=A2.indexOf($.charAt(B++)),q=J<<2|Z>>4,Q=(Z&15)<<4|G>>2,K=(G&3)<<6|W,F[V++]=q,G!==64)F[V++]=Q;if(W!==64)F[V++]=K}return F}});var T6=N0((vz,q$)=>{q$.exports={isNode:typeof Buffer<"u",newBufferFrom:function($,q){if(Buffer.from&&Buffer.from!==Uint8Array.from)return Buffer.from($,q);else{if(typeof $==="number")throw Error('The "data" argument must not be a number');return new Buffer($,q)}},allocBuffer:function($){if(Buffer.alloc)return Buffer.alloc($);else{var q=new Buffer($);return q.fill(0),q}},isBuffer:function($){return Buffer.isBuffer($)},isStream:function($){return $&&typeof $.on==="function"&&typeof $.pause==="function"&&typeof $.resume==="function"}}});var V$=N0((fz,J$)=>{var K$=global.MutationObserver||global.WebKitMutationObserver,u6;if(K$)C8=0,o5=new K$(I8),j8=global.document.createTextNode(""),o5.observe(j8,{characterData:!0}),u6=function(){j8.data=C8=++C8%2};else if(!global.setImmediate&&typeof global.MessageChannel<"u")g8=new global.MessageChannel,g8.port1.onmessage=I8,u6=function(){g8.port2.postMessage(0)};else if("document"in global&&"onreadystatechange"in global.document.createElement("script"))u6=function(){var $=global.document.createElement("script");$.onreadystatechange=function(){I8(),$.onreadystatechange=null,$.parentNode.removeChild($),$=null},global.document.documentElement.appendChild($)};else u6=function(){setTimeout(I8,0)};var C8,o5,j8,g8,a5,S6=[];function I8(){a5=!0;var $,q,Q=S6.length;while(Q){q=S6,S6=[],$=-1;while(++${var uV=V$();function l1(){}var o0={},U$=["REJECTED"],l5=["FULFILLED"],Z$=["PENDING"];B$.exports=t2;function t2($){if(typeof $!=="function")throw TypeError("resolver must be a function");if(this.state=Z$,this.queue=[],this.outcome=void 0,$!==l1)G$(this,$)}t2.prototype.finally=function($){if(typeof $!=="function")return this;var q=this.constructor;return this.then(Q,K);function Q(J){function Z(){return J}return q.resolve($()).then(Z)}function K(J){function Z(){throw J}return q.resolve($()).then(Z)}};t2.prototype.catch=function($){return this.then(null,$)};t2.prototype.then=function($,q){if(typeof $!=="function"&&this.state===l5||typeof q!=="function"&&this.state===U$)return this;var Q=new this.constructor(l1);if(this.state!==Z$){var K=this.state===l5?$:q;r5(Q,K,this.outcome)}else this.queue.push(new E6(Q,$,q));return Q};function E6($,q,Q){if(this.promise=$,typeof q==="function")this.onFulfilled=q,this.callFulfilled=this.otherCallFulfilled;if(typeof Q==="function")this.onRejected=Q,this.callRejected=this.otherCallRejected}E6.prototype.callFulfilled=function($){o0.resolve(this.promise,$)};E6.prototype.otherCallFulfilled=function($){r5(this.promise,this.onFulfilled,$)};E6.prototype.callRejected=function($){o0.reject(this.promise,$)};E6.prototype.otherCallRejected=function($){r5(this.promise,this.onRejected,$)};function r5($,q,Q){uV(function(){var K;try{K=q(Q)}catch(J){return o0.reject($,J)}if(K===$)o0.reject($,TypeError("Cannot resolve promise with itself"));else o0.resolve($,K)})}o0.resolve=function($,q){var Q=W$(SV,q);if(Q.status==="error")return o0.reject($,Q.value);var K=Q.value;if(K)G$($,K);else{$.state=l5,$.outcome=q;var J=-1,Z=$.queue.length;while(++J{var s5=null;if(typeof Promise<"u")s5=Promise;else s5=z$();F$.exports={Promise:s5}});var w$=N0((M$)=>{(function($,q){if($.setImmediate)return;var Q=1,K={},J=!1,Z=$.document,G;function W(z){if(typeof z!=="function")z=Function(""+z);var N=Array(arguments.length-1);for(var H=0;H"u"?typeof global>"u"?M$:global:self)});var T0=N0((_0)=>{var e2=n2(),nV=i5(),s1=T6(),t5=r1();w$();function dV($){var q=null;if(e2.uint8array)q=new Uint8Array($.length);else q=Array($.length);return X8($,q)}_0.newBlob=function($,q){_0.checkSupport("blob");try{return new Blob([$],{type:q})}catch(J){try{var Q=self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder,K=new Q;return K.append($),K.getBlob(q)}catch(Z){throw Error("Bug : can't construct the Blob.")}}};function _6($){return $}function X8($,q){for(var Q=0;Q<$.length;++Q)q[Q]=$.charCodeAt(Q)&255;return q}var A8={stringifyByChunk:function($,q,Q){var K=[],J=0,Z=$.length;if(Z<=Q)return String.fromCharCode.apply(null,$);while(J1)try{return A8.stringifyByChunk($,Q,q)}catch(J){q=Math.floor(q/2)}return A8.stringifyByChar($)}_0.applyFromCharCode=c6;function y8($,q){for(var Q=0;Q<$.length;Q++)q[Q]=$[Q];return q}var $1={};$1.string={string:_6,array:function($){return X8($,Array($.length))},arraybuffer:function($){return $1.string.uint8array($).buffer},uint8array:function($){return X8($,new Uint8Array($.length))},nodebuffer:function($){return X8($,s1.allocBuffer($.length))}};$1.array={string:c6,array:_6,arraybuffer:function($){return new Uint8Array($).buffer},uint8array:function($){return new Uint8Array($)},nodebuffer:function($){return s1.newBufferFrom($)}};$1.arraybuffer={string:function($){return c6(new Uint8Array($))},array:function($){return y8(new Uint8Array($),Array($.byteLength))},arraybuffer:_6,uint8array:function($){return new Uint8Array($)},nodebuffer:function($){return s1.newBufferFrom(new Uint8Array($))}};$1.uint8array={string:c6,array:function($){return y8($,Array($.length))},arraybuffer:function($){return $.buffer},uint8array:_6,nodebuffer:function($){return s1.newBufferFrom($)}};$1.nodebuffer={string:c6,array:function($){return y8($,Array($.length))},arraybuffer:function($){return $1.nodebuffer.uint8array($).buffer},uint8array:function($){return y8($,new Uint8Array($.length))},nodebuffer:_6};_0.transformTo=function($,q){if(!q)q="";if(!$)return q;_0.checkSupport($);var Q=_0.getTypeOf(q),K=$1[Q][$](q);return K};_0.resolve=function($){var q=$.split("/"),Q=[];for(var K=0;K"u")$[Q]=arguments[q][Q];return $};_0.prepareContent=function($,q,Q,K,J){var Z=t5.Promise.resolve(q).then(function(G){var W=e2.blob&&(G instanceof Blob||["[object File]","[object Blob]"].indexOf(Object.prototype.toString.call(G))!==-1);if(W&&typeof FileReader<"u")return new t5.Promise(function(B,V){var U=new FileReader;U.onload=function(w){B(w.target.result)},U.onerror=function(w){V(w.target.error)},U.readAsArrayBuffer(G)});else return G});return Z.then(function(G){var W=_0.getTypeOf(G);if(!W)return t5.Promise.reject(Error("Can't read the data of '"+$+"'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?"));if(W==="arraybuffer")G=_0.transformTo("uint8array",G);else if(W==="string"){if(J)G=nV.decode(G);else if(Q){if(K!==!0)G=dV(G)}}return G})}});var V2=N0((gz,Y$)=>{function N$($){this.name=$||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}N$.prototype={push:function($){this.emit("data",$)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch($){this.emit("error",$)}return!0},error:function($){if(this.isFinished)return!1;if(this.isPaused)this.generatedError=$;else{if(this.isFinished=!0,this.emit("error",$),this.previous)this.previous.error($);this.cleanUp()}return!0},on:function($,q){return this._listeners[$].push(q),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function($,q){if(this._listeners[$])for(var Q=0;Q "+$;else return $}};Y$.exports=N$});var e1=N0((Q1)=>{var t1=T0(),L1=n2(),mV=T6(),h8=V2(),b6=Array(256);for(X2=0;X2<256;X2++)b6[X2]=X2>=252?6:X2>=248?5:X2>=240?4:X2>=224?3:X2>=192?2:1;var X2;b6[254]=b6[254]=1;var pV=function($){var q,Q,K,J,Z,G=$.length,W=0;for(J=0;J>>6,q[Z++]=128|Q&63;else if(Q<65536)q[Z++]=224|Q>>>12,q[Z++]=128|Q>>>6&63,q[Z++]=128|Q&63;else q[Z++]=240|Q>>>18,q[Z++]=128|Q>>>12&63,q[Z++]=128|Q>>>6&63,q[Z++]=128|Q&63}return q},iV=function($,q){var Q;if(q=q||$.length,q>$.length)q=$.length;Q=q-1;while(Q>=0&&($[Q]&192)===128)Q--;if(Q<0)return q;if(Q===0)return q;return Q+b6[$[Q]]>q?Q:q},oV=function($){var q,Q,K,J,Z=$.length,G=Array(Z*2);for(Q=0,q=0;q4){G[Q++]=65533,q+=J-1;continue}K&=J===2?31:J===3?15:7;while(J>1&&q1){G[Q++]=65533;continue}if(K<65536)G[Q++]=K;else K-=65536,G[Q++]=55296|K>>10&1023,G[Q++]=56320|K&1023}if(G.length!==Q)if(G.subarray)G=G.subarray(0,Q);else G.length=Q;return t1.applyFromCharCode(G)};Q1.utf8encode=function(q){if(L1.nodebuffer)return mV.newBufferFrom(q,"utf-8");return pV(q)};Q1.utf8decode=function(q){if(L1.nodebuffer)return t1.transformTo("nodebuffer",q).toString("utf-8");return q=t1.transformTo(L1.uint8array?"uint8array":"array",q),oV(q)};function x8(){h8.call(this,"utf-8 decode"),this.leftOver=null}t1.inherits(x8,h8);x8.prototype.processChunk=function($){var q=t1.transformTo(L1.uint8array?"uint8array":"array",$.data);if(this.leftOver&&this.leftOver.length){if(L1.uint8array){var Q=q;q=new Uint8Array(Q.length+this.leftOver.length),q.set(this.leftOver,0),q.set(Q,this.leftOver.length)}else q=this.leftOver.concat(q);this.leftOver=null}var K=iV(q),J=q;if(K!==q.length)if(L1.uint8array)J=q.subarray(0,K),this.leftOver=q.subarray(K,q.length);else J=q.slice(0,K),this.leftOver=q.slice(K,q.length);this.push({data:Q1.utf8decode(J),meta:$.meta})};x8.prototype.flush=function(){if(this.leftOver&&this.leftOver.length)this.push({data:Q1.utf8decode(this.leftOver),meta:{}}),this.leftOver=null};Q1.Utf8DecodeWorker=x8;function e5(){h8.call(this,"utf-8 encode")}t1.inherits(e5,h8);e5.prototype.processChunk=function($){this.push({data:Q1.utf8encode($.data),meta:$.meta})};Q1.Utf8EncodeWorker=e5});var H$=N0((Xz,L$)=>{var k$=V2(),D$=T0();function $4($){k$.call(this,"ConvertWorker to "+$),this.destType=$}D$.inherits($4,k$);$4.prototype.processChunk=function($){this.push({data:D$.transformTo(this.destType,$.data),meta:$.meta})};L$.exports=$4});var R$=N0((yz,f$)=>{var v$=d5().Readable,aV=T0();aV.inherits(Q4,v$);function Q4($,q,Q){v$.call(this,q),this._helper=$;var K=this;$.on("data",function(J,Z){if(!K.push(J))K._helper.pause();if(Q)Q(Z)}).on("error",function(J){K.emit("error",J)}).on("end",function(){K.push(null)})}Q4.prototype._read=function(){this._helper.resume()};f$.exports=Q4});var q4=N0((hz,j$)=>{var H1=T0(),lV=H$(),rV=V2(),sV=i5(),tV=n2(),eV=r1(),I$=null;if(tV.nodestream)try{I$=R$()}catch($){}function $U($,q,Q){switch($){case"blob":return H1.newBlob(H1.transformTo("arraybuffer",q),Q);case"base64":return sV.encode(q);default:return H1.transformTo($,q)}}function QU($,q){var Q,K=0,J=null,Z=0;for(Q=0;Q{D2.base64=!1;D2.binary=!1;D2.dir=!1;D2.createFolders=!0;D2.date=null;D2.compression=null;D2.compressionOptions=null;D2.comment=null;D2.unixPermissions=null;D2.dosPermissions=null});var J4=N0((Oz,g$)=>{var O8=T0(),P8=V2(),KU=16384;function $6($){P8.call(this,"DataWorker");var q=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,$.then(function(Q){if(q.dataIsReady=!0,q.data=Q,q.max=Q&&Q.length||0,q.type=O8.getTypeOf(Q),!q.isPaused)q._tickAndRepeat()},function(Q){q.error(Q)})}O8.inherits($6,P8);$6.prototype.cleanUp=function(){P8.prototype.cleanUp.call(this),this.data=null};$6.prototype.resume=function(){if(!P8.prototype.resume.call(this))return!1;if(!this._tickScheduled&&this.dataIsReady)this._tickScheduled=!0,O8.delay(this._tickAndRepeat,[],this);return!0};$6.prototype._tickAndRepeat=function(){if(this._tickScheduled=!1,this.isPaused||this.isFinished)return;if(this._tick(),!this.isFinished)O8.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0};$6.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var $=KU,q=null,Q=Math.min(this.max,this.index+$);if(this.index>=this.max)return this.end();else{switch(this.type){case"string":q=this.data.substring(this.index,Q);break;case"uint8array":q=this.data.subarray(this.index,Q);break;case"array":case"nodebuffer":q=this.data.slice(this.index,Q);break}return this.index=Q,this.push({data:q,meta:{percent:this.max?this.index/this.max*100:0}})}};g$.exports=$6});var T8=N0((Pz,X$)=>{var JU=T0();function VU(){var $,q=[];for(var Q=0;Q<256;Q++){$=Q;for(var K=0;K<8;K++)$=$&1?3988292384^$>>>1:$>>>1;q[Q]=$}return q}var A$=VU();function UU($,q,Q,K){var J=A$,Z=K+Q;$=$^-1;for(var G=K;G