More resilient preview script injection and postMessage communication (#12)

This commit is contained in:
Mateusz Burzyński
2025-02-04 20:45:18 +01:00
committed by GitHub
parent 547b027ef7
commit aec72dd575
7 changed files with 259 additions and 263 deletions

View File

@@ -25,7 +25,6 @@ import { BinaryContent } from './BinaryContent';
import { getTheme, reconfigureTheme } from './cm-theme';
import { indentKeyBinding } from './indent';
import { getLanguage } from './languages';
import { removeRecordingMessageHandler } from '~/lib/replay/Recording';
const logger = createScopedLogger('CodeMirrorEditor');
@@ -276,7 +275,6 @@ function newEditorState(
onFileSaveRef: MutableRefObject<OnSaveCallback | undefined>,
extensions: Extension[],
) {
content = removeRecordingMessageHandler(content);
return EditorState.create({
doc: content,
extensions: [
@@ -383,7 +381,7 @@ function setEditorDocument(
autoFocus: boolean,
doc: TextEditorDocument,
) {
const content = removeRecordingMessageHandler(doc.value);
const content = doc.value;
if (content !== view.state.doc.toString()) {
view.dispatch({

View File

@@ -1,30 +1,66 @@
// Manage state around recording Preview behavior for generating a Replay recording.
import { assert, stringToBase64, uint8ArrayToBase64 } from "./ReplayProtocolClient";
import type { IndexedDBAccess, LocalStorageAccess, NetworkResource, SimulationData, UserInteraction } from "./SimulationData";
import { assert, stringToBase64, uint8ArrayToBase64 } from './ReplayProtocolClient';
import type {
IndexedDBAccess,
LocalStorageAccess,
NetworkResource,
SimulationData,
UserInteraction,
} from './SimulationData';
// Our message event listener can trigger on messages from iframes we don't expect.
// This is a unique ID for the last time we injected the recording message handler
// logic into an iframe. We will ignore messages from other injected handlers.
let gLastMessageHandlerId = "";
type Compute<T> = { [K in keyof T]: T[K] } & unknown;
type RequestMap = {
'recording-data': {
payload: unknown;
response: ArrayBufferLike;
};
'mouse-data': {
payload: { x: number; y: number };
response: MouseData;
};
};
type Request = {
[K in keyof RequestMap]: Compute<
{ request: K } & (undefined extends RequestMap[K]['payload']
? { payload?: RequestMap[K]['payload'] }
: { payload: RequestMap[K]['payload'] })
>;
}[keyof RequestMap];
let lastRequestId = 0;
function sendIframeRequest<K extends keyof RequestMap>(
iframe: HTMLIFrameElement,
request: Extract<Request, { request: K }>,
) {
assert(iframe.contentWindow);
const target = iframe.contentWindow;
const requestId = ++lastRequestId;
target.postMessage({ id: requestId, request, source: '@@replay-nut' }, '*');
return new Promise<RequestMap[K]['response']>((resolve) => {
const handler = (event: MessageEvent) => {
if (event.data?.source !== '@@replay-nut' || event.source !== target || event.data?.id !== requestId) {
return;
}
window.removeEventListener('message', handler);
resolve(event.data.response);
};
window.addEventListener('message', handler);
});
}
export async function getIFrameSimulationData(iframe: HTMLIFrameElement): Promise<SimulationData> {
assert(iframe.contentWindow);
iframe.contentWindow.postMessage({ source: "recording-data-request" }, "*");
const buffer = await sendIframeRequest(iframe, { request: 'recording-data' });
const decoder = new TextDecoder();
const jsonString = decoder.decode(new Uint8Array(buffer));
const data = await new Promise((resolve) => {
window.addEventListener("message", (event) => {
if (event.data?.source == "recording-data-response" &&
event.data?.messageHandlerId == gLastMessageHandlerId) {
const decoder = new TextDecoder();
const jsonString = decoder.decode(event.data.buffer);
const data = JSON.parse(jsonString) as SimulationData;
resolve(data);
}
});
});
return data as SimulationData;
return JSON.parse(jsonString) as SimulationData;
}
export interface MouseData {
@@ -36,23 +72,11 @@ export interface MouseData {
}
export async function getMouseData(iframe: HTMLIFrameElement, position: { x: number; y: number }): Promise<MouseData> {
assert(iframe.contentWindow);
iframe.contentWindow.postMessage({ source: "mouse-data-request", position }, "*");
const mouseData = await new Promise((resolve) => {
window.addEventListener("message", (event) => {
if (event.data?.source == "mouse-data-response" &&
event.data?.messageHandlerId == gLastMessageHandlerId) {
resolve(event.data.mouseData);
}
});
});
return mouseData as MouseData;
return sendIframeRequest(iframe, { request: 'mouse-data', payload: position });
}
// Add handlers to the current iframe's window.
function addRecordingMessageHandler(messageHandlerId: string) {
function addRecordingMessageHandler() {
const resources: NetworkResource[] = [];
const interactions: UserInteraction[] = [];
const indexedDBAccesses: IndexedDBAccess[] = [];
@@ -66,7 +90,7 @@ function addRecordingMessageHandler(messageHandlerId: string) {
}
function addTextResource(info: RequestInfo, text: string, responseHeaders: Record<string, string>) {
const url = (new URL(info.url, window.location.href)).href;
const url = new URL(info.url, window.location.href).href;
resources.push({
url,
requestBodyBase64: stringToBase64(info.requestBody),
@@ -80,34 +104,34 @@ function addRecordingMessageHandler(messageHandlerId: string) {
const data: SimulationData = [];
data.push({
kind: "locationHref",
kind: 'locationHref',
href: window.location.href,
});
data.push({
kind: "documentURL",
kind: 'documentURL',
url: window.location.href,
});
for (const resource of resources) {
data.push({
kind: "resource",
kind: 'resource',
resource,
});
}
for (const interaction of interactions) {
data.push({
kind: "interaction",
kind: 'interaction',
interaction,
});
}
for (const indexedDBAccess of indexedDBAccesses) {
data.push({
kind: "indexedDB",
kind: 'indexedDB',
access: indexedDBAccess,
});
}
for (const localStorageAccess of localStorageAccesses) {
data.push({
kind: "localStorage",
kind: 'localStorage',
access: localStorageAccess,
});
}
@@ -115,44 +139,56 @@ function addRecordingMessageHandler(messageHandlerId: string) {
return data;
}
window.addEventListener("message", async (event) => {
switch (event.data?.source) {
case "recording-data-request": {
async function handleRequest<T extends Request>({
request,
payload,
}: Request): Promise<RequestMap[T['request']]['response']> {
switch (request) {
case 'recording-data': {
const data = await getSimulationData();
const encoder = new TextEncoder();
const serializedData = encoder.encode(JSON.stringify(data));
const buffer = serializedData.buffer;
window.parent.postMessage({ source: "recording-data-response", buffer, messageHandlerId }, "*", [buffer]);
break;
return buffer;
}
case "mouse-data-request": {
const { x, y } = event.data.position;
case 'mouse-data': {
const { x, y } = payload;
const element = document.elementFromPoint(x, y);
assert(element);
const selector = computeSelector(element);
const rect = element.getBoundingClientRect();
const mouseData: MouseData = {
return {
selector,
width: rect.width,
height: rect.height,
x: x - rect.x,
y: y - rect.y,
};
window.parent.postMessage({ source: "mouse-data-response", mouseData, messageHandlerId }, "*");
break;
}
}
}
window.addEventListener('message', async (event) => {
if (event.data?.source !== '@@replay-nut') {
return;
}
const response = await handleRequest(event.data.request);
window.parent.postMessage({ id: event.data.id, response, source: '@@replay-nut' }, '*');
});
// Evaluated function to find the selector and associated data.
function getMouseEventData(event: MouseEvent) {
assert(event.target);
const target = event.target as Element;
const selector = computeSelector(target);
const rect = target.getBoundingClientRect();
return {
selector,
width: rect.width,
@@ -164,8 +200,10 @@ function addRecordingMessageHandler(messageHandlerId: string) {
function getKeyboardEventData(event: KeyboardEvent) {
assert(event.target);
const target = event.target as Element;
const selector = computeSelector(target);
return {
selector,
key: event.key,
@@ -192,7 +230,7 @@ function addRecordingMessageHandler(messageHandlerId: string) {
if (parent) {
const siblings = Array.from(parent.children);
const index = siblings.indexOf(current) + 1;
if (siblings.filter(el => el.tagName === current!.tagName).length > 1) {
if (siblings.filter((el) => el.tagName === current!.tagName).length > 1) {
selector += `:nth-child(${index})`;
}
}
@@ -201,50 +239,58 @@ function addRecordingMessageHandler(messageHandlerId: string) {
current = current.parentElement;
}
return path.join(" > ");
return path.join(' > ');
}
window.addEventListener("click", (event) => {
if (event.target) {
interactions.push({
kind: "click",
time: Date.now() - startTime,
...getMouseEventData(event)
});
}
}, { capture: true, passive: true });
window.addEventListener(
'click',
(event) => {
if (event.target) {
interactions.push({
kind: 'click',
time: Date.now() - startTime,
...getMouseEventData(event),
});
}
},
{ capture: true, passive: true },
);
window.addEventListener("dblclick", (event) => {
if (event.target) {
interactions.push({
kind: "dblclick",
time: Date.now() - startTime,
...getMouseEventData(event)
});
}
}, { capture: true, passive: true });
window.addEventListener(
'dblclick',
(event) => {
if (event.target) {
interactions.push({
kind: 'dblclick',
time: Date.now() - startTime,
...getMouseEventData(event),
});
}
},
{ capture: true, passive: true },
);
window.addEventListener("keydown", (event) => {
if (event.key) {
interactions.push({
kind: "keydown",
time: Date.now() - startTime,
...getKeyboardEventData(event)
});
}
}, { capture: true, passive: true });
window.addEventListener(
'keydown',
(event) => {
if (event.key) {
interactions.push({
kind: 'keydown',
time: Date.now() - startTime,
...getKeyboardEventData(event),
});
}
},
{ capture: true, passive: true },
);
function onInterceptedOperation(name: string) {
console.log(`InterceptedOperation ${name}`);
}
function interceptProperty(
obj: object,
prop: string,
interceptor: (basevalue: any) => any
) {
function interceptProperty(obj: object, prop: string, interceptor: (basevalue: any) => any) {
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
assert(descriptor?.get, "Property must have a getter");
assert(descriptor?.get, 'Property must have a getter');
let interceptValue: any;
Object.defineProperty(obj, prop, {
@@ -261,31 +307,26 @@ function addRecordingMessageHandler(messageHandlerId: string) {
}
const IDBFactoryMethods = {
_name: "IDBFactory",
open: (v: any) => createFunctionProxy(v, "open"),
_name: 'IDBFactory',
open: (v: any) => createFunctionProxy(v, 'open'),
};
const IDBOpenDBRequestMethods = {
_name: "IDBOpenDBRequest",
_name: 'IDBOpenDBRequest',
result: createProxy,
};
const IDBDatabaseMethods = {
_name: "IDBDatabase",
transaction: (v: any) => createFunctionProxy(v, "transaction"),
_name: 'IDBDatabase',
transaction: (v: any) => createFunctionProxy(v, 'transaction'),
};
const IDBTransactionMethods = {
_name: "IDBTransaction",
objectStore: (v: any) => createFunctionProxy(v, "objectStore"),
_name: 'IDBTransaction',
objectStore: (v: any) => createFunctionProxy(v, 'objectStore'),
};
function pushIndexedDBAccess(
request: IDBRequest,
kind: IndexedDBAccess["kind"],
key: any,
item: any
) {
function pushIndexedDBAccess(request: IDBRequest, kind: IndexedDBAccess['kind'], key: any, item: any) {
indexedDBAccesses.push({
kind,
key,
@@ -300,54 +341,50 @@ function addRecordingMessageHandler(messageHandlerId: string) {
const getRequestKeys: Map<IDBRequest, any> = new Map();
const IDBObjectStoreMethods = {
_name: "IDBObjectStore",
_name: 'IDBObjectStore',
get: (v: any) =>
createFunctionProxy(v, "get", (request, key) => {
createFunctionProxy(v, 'get', (request, key) => {
// Wait to add the request until the value is known.
getRequestKeys.set(request, key);
return createProxy(request);
}),
put: (v: any) =>
createFunctionProxy(v, "put", (request, item, key) => {
pushIndexedDBAccess(request, "put", key, item);
createFunctionProxy(v, 'put', (request, item, key) => {
pushIndexedDBAccess(request, 'put', key, item);
return createProxy(request);
}),
add: (v: any) =>
createFunctionProxy(v, "add", (request, item, key) => {
pushIndexedDBAccess(request, "add", key, item);
createFunctionProxy(v, 'add', (request, item, key) => {
pushIndexedDBAccess(request, 'add', key, item);
return createProxy(request);
}),
};
const IDBRequestMethods = {
_name: "IDBRequest",
_name: 'IDBRequest',
result: (value: any, target: any) => {
const key = getRequestKeys.get(target);
if (key) {
pushIndexedDBAccess(target, "get", key, value);
pushIndexedDBAccess(target, 'get', key, value);
}
return value;
},
};
function pushLocalStorageAccess(
kind: LocalStorageAccess["kind"],
key: string,
value?: string
) {
function pushLocalStorageAccess(kind: LocalStorageAccess['kind'], key: string, value?: string) {
localStorageAccesses.push({ kind, key, value });
}
const StorageMethods = {
_name: "Storage",
_name: 'Storage',
getItem: (v: any) =>
createFunctionProxy(v, "getItem", (value: string, key: string) => {
pushLocalStorageAccess("get", key, value);
createFunctionProxy(v, 'getItem', (value: string, key: string) => {
pushLocalStorageAccess('get', key, value);
return value;
}),
setItem: (v: any) =>
createFunctionProxy(v, "setItem", (_rv: undefined, key: string) => {
pushLocalStorageAccess("set", key);
createFunctionProxy(v, 'setItem', (_rv: undefined, key: string) => {
pushLocalStorageAccess('set', key);
}),
};
@@ -363,9 +400,9 @@ function addRecordingMessageHandler(messageHandlerId: string) {
}
const ResponseMethods = {
_name: "Response",
_name: 'Response',
json: (v: any, response: Response) =>
createFunctionProxy(v, "json", async (promise: Promise<any>) => {
createFunctionProxy(v, 'json', async (promise: Promise<any>) => {
const json = await promise;
const requestInfo = responseToRequestInfo.get(response);
if (requestInfo) {
@@ -374,7 +411,7 @@ function addRecordingMessageHandler(messageHandlerId: string) {
return json;
}),
text: (v: any, response: Response) =>
createFunctionProxy(v, "text", async (promise: Promise<any>) => {
createFunctionProxy(v, 'text', async (promise: Promise<any>) => {
const text = await promise;
const requestInfo = responseToRequestInfo.get(response);
if (requestInfo) {
@@ -403,14 +440,14 @@ function addRecordingMessageHandler(messageHandlerId: string) {
} else if (obj instanceof Response) {
methods = ResponseMethods;
}
assert(methods, "Unknown object for createProxy");
assert(methods, 'Unknown object for createProxy');
const name = methods._name;
return new Proxy(obj, {
get(target, prop) {
onInterceptedOperation(`ProxyGetter:${name}.${String(prop)}`);
let value = target[prop];
if (typeof value === "function") {
if (typeof value === 'function') {
value = value.bind(target);
}
if (methods[prop]) {
@@ -427,11 +464,7 @@ function addRecordingMessageHandler(messageHandlerId: string) {
});
}
function createFunctionProxy(
fn: any,
name: string,
handler?: (v: any, ...args: any[]) => any
) {
function createFunctionProxy(fn: any, name: string, handler?: (v: any, ...args: any[]) => any) {
return (...args: any[]) => {
onInterceptedOperation(`FunctionCall:${name}`);
const v = fn(...args);
@@ -439,13 +472,13 @@ function addRecordingMessageHandler(messageHandlerId: string) {
};
}
interceptProperty(window, "indexedDB", createProxy);
interceptProperty(window, "localStorage", createProxy);
interceptProperty(window, 'indexedDB', createProxy);
interceptProperty(window, 'localStorage', createProxy);
const baseFetch = window.fetch;
window.fetch = async (info, options) => {
const url = info instanceof Request ? info.url : info.toString();
const requestBody = (typeof options?.body == "string") ? options.body : "";
const requestBody = typeof options?.body == 'string' ? options.body : '';
const requestInfo: RequestInfo = { url, requestBody };
try {
const rv = await baseFetch(info, options);
@@ -462,40 +495,9 @@ function addRecordingMessageHandler(messageHandlerId: string) {
};
}
const RecordingMessageHandlerScriptPrefix = `
<script>
export const recordingMessageHandlerScript = `
${assert}
${stringToBase64}
${uint8ArrayToBase64}
(${addRecordingMessageHandler})
(${addRecordingMessageHandler})()
`;
export function injectRecordingMessageHandler(content: string) {
const headTag = content.indexOf("<head>");
assert(headTag != -1, "No <head> tag found");
const headEnd = headTag + 6;
gLastMessageHandlerId = Math.random().toString(36).substring(2, 15);
const text = `${RecordingMessageHandlerScriptPrefix}("${gLastMessageHandlerId}")</script>`;
return content.slice(0, headEnd) + text + content.slice(headEnd);
}
export function removeRecordingMessageHandler(content: string) {
const index = content.indexOf(RecordingMessageHandlerScriptPrefix);
if (index == -1) {
return content;
}
const prefix = content.substring(0, index);
const suffixStart = index + RecordingMessageHandlerScriptPrefix.length;
const closeScriptTag = "</script>";
const closeScriptIndex = content.indexOf(closeScriptTag, suffixStart);
assert(closeScriptIndex != -1, "No </script> tag found");
const suffix = content.substring(closeScriptIndex + closeScriptTag.length);
return prefix + suffix;
}

View File

@@ -6,7 +6,6 @@ import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable';
import type { ActionCallbackData } from './message-parser';
import type { BoltShell } from '~/utils/shell';
import { injectRecordingMessageHandler } from '~/lib/replay/Recording';
const logger = createScopedLogger('ActionRunner');
@@ -294,11 +293,7 @@ export class ActionRunner {
}
try {
let content = action.content;
if (relativePath == "../../index.html") {
content = injectRecordingMessageHandler(action.content);
}
await webcontainer.fs.writeFile(relativePath, content);
await webcontainer.fs.writeFile(relativePath, action.content);
logger.debug(`File written ${relativePath}`);
} catch (error) {
logger.error('Failed to write file\n\n', error);

View File

@@ -17,7 +17,6 @@ import { extractRelativePath } from '~/utils/diff';
import { description } from '~/lib/persistence';
import Cookies from 'js-cookie';
import { createSampler } from '~/utils/sampler';
import { removeRecordingMessageHandler } from '~/lib/replay/Recording';
import { uint8ArrayToBase64 } from '../replay/ReplayProtocolClient';
import type { ActionAlert } from '~/types/actions';
@@ -385,7 +384,7 @@ export class WorkbenchStore {
for (const [filePath, dirent] of Object.entries(files)) {
if (dirent?.type === 'file' && !dirent.isBinary) {
const relativePath = extractRelativePath(filePath);
const content = removeRecordingMessageHandler(dirent.content);
const content = dirent.content;
// split the path into segments
const pathSegments = relativePath.split('/');

View File

@@ -1,6 +1,7 @@
import { WebContainer } from '@webcontainer/api';
import { WORK_DIR_NAME } from '~/utils/constants';
import { cleanStackTrace } from '~/utils/stacktrace';
import { recordingMessageHandlerScript } from '../replay/Recording';
interface WebContainerContext {
loaded: boolean;
@@ -30,6 +31,7 @@ if (!import.meta.env.SSR) {
});
})
.then(async (webcontainer) => {
await webcontainer.setPreviewScript(recordingMessageHandlerScript);
webcontainerContext.loaded = true;
const { workbenchStore } = await import('~/lib/stores/workbench');

View File

@@ -71,7 +71,7 @@
"@remix-run/react": "^2.15.0",
"@uiw/codemirror-theme-vscode": "^4.23.6",
"@unocss/reset": "^0.61.9",
"@webcontainer/api": "1.3.0-internal.10",
"@webcontainer/api": "1.5.1-internal.8",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
@@ -124,7 +124,7 @@
"pnpm": "^9.14.4",
"prettier": "^3.4.1",
"sass-embedded": "^1.81.0",
"typescript": "^5.7.2",
"typescript": "5.8.0-beta",
"unified": "^11.0.5",
"unocss": "^0.61.9",
"vite": "^5.4.11",

172
pnpm-lock.yaml generated
View File

@@ -121,13 +121,13 @@ importers:
version: 1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@remix-run/cloudflare':
specifier: ^2.15.0
version: 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)
version: 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)
'@remix-run/cloudflare-pages':
specifier: ^2.15.0
version: 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)
version: 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)
'@remix-run/react':
specifier: ^2.15.0
version: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)
version: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta)
'@uiw/codemirror-theme-vscode':
specifier: ^4.23.6
version: 4.23.6(@codemirror/language@6.10.6)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)
@@ -135,8 +135,8 @@ importers:
specifier: ^0.61.9
version: 0.61.9
'@webcontainer/api':
specifier: 1.3.0-internal.10
version: 1.3.0-internal.10
specifier: 1.5.1-internal.8
version: 1.5.1-internal.8
'@xterm/addon-fit':
specifier: ^0.10.0
version: 0.10.0(@xterm/xterm@5.5.0)
@@ -226,10 +226,10 @@ importers:
version: 4.0.0
remix-island:
specifier: ^0.2.0
version: 0.2.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/server-runtime@2.15.0(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 0.2.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@remix-run/server-runtime@2.15.0(typescript@5.8.0-beta))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
remix-utils:
specifier: ^7.7.0
version: 7.7.0(@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2))(@remix-run/node@2.15.0(typescript@5.7.2))(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.23.8)
version: 7.7.0(@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta))(@remix-run/node@2.15.0(typescript@5.8.0-beta))(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.23.8)
shiki:
specifier: ^1.24.0
version: 1.24.0
@@ -239,13 +239,13 @@ importers:
devDependencies:
'@blitz/eslint-plugin':
specifier: 0.1.0
version: 0.1.0(@types/eslint@8.56.10)(jiti@1.21.6)(prettier@3.4.1)(typescript@5.7.2)
version: 0.1.0(@types/eslint@8.56.10)(jiti@1.21.6)(prettier@3.4.1)(typescript@5.8.0-beta)
'@cloudflare/workers-types':
specifier: ^4.20241127.0
version: 4.20241127.0
'@remix-run/dev':
specifier: ^2.15.0
version: 2.15.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@types/node@22.10.1)(sass-embedded@1.81.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))(wrangler@3.91.0(@cloudflare/workers-types@4.20241127.0))
version: 2.15.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@types/node@22.10.1)(sass-embedded@1.81.0)(typescript@5.8.0-beta)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))(wrangler@3.91.0(@cloudflare/workers-types@4.20241127.0))
'@types/diff':
specifier: ^5.2.3
version: 5.2.3
@@ -289,8 +289,8 @@ importers:
specifier: ^1.81.0
version: 1.81.0
typescript:
specifier: ^5.7.2
version: 5.7.2
specifier: 5.8.0-beta
version: 5.8.0-beta
unified:
specifier: ^11.0.5
version: 11.0.5
@@ -308,7 +308,7 @@ importers:
version: 1.1.0(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))
vite-tsconfig-paths:
specifier: ^4.3.2
version: 4.3.2(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))
version: 4.3.2(typescript@5.8.0-beta)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))
vitest:
specifier: ^2.1.7
version: 2.1.8(@types/node@22.10.1)(sass-embedded@1.81.0)
@@ -2702,8 +2702,8 @@ packages:
'@web3-storage/multipart-parser@1.0.0':
resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==}
'@webcontainer/api@1.3.0-internal.10':
resolution: {integrity: sha512-iuqjuDX2uADiJMYZok7+tJqVCJYZ+tU2NwVtxlvakRWSSmIFBGrJ38pD0C5igaOnBV8C9kGDjCE6B03SvLtN4Q==}
'@webcontainer/api@1.5.1-internal.8':
resolution: {integrity: sha512-EgtnRLOIFhBiTS/1nQmg3A6RtQXvp+kDK08cbEZZpnXGyaNd1y9dSCJUEn3OUCuHSEZr3LeqBtwR5mYOxFeiUQ==}
'@xterm/addon-fit@0.10.0':
resolution: {integrity: sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==}
@@ -5764,8 +5764,8 @@ packages:
typescript:
optional: true
typescript@5.7.2:
resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
typescript@5.8.0-beta:
resolution: {integrity: sha512-7VGUiBOGi+BYhiuy3iITIgu6m2wVW2Vb4CW+OJsW6OJS/TgvezKbAN3WBfiSErE8QOLdce0ilm6VANMkzNWW1A==}
engines: {node: '>=14.17'}
hasBin: true
@@ -6955,19 +6955,19 @@ snapshots:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@blitz/eslint-plugin@0.1.0(@types/eslint@8.56.10)(jiti@1.21.6)(prettier@3.4.1)(typescript@5.7.2)':
'@blitz/eslint-plugin@0.1.0(@types/eslint@8.56.10)(jiti@1.21.6)(prettier@3.4.1)(typescript@5.8.0-beta)':
dependencies:
'@stylistic/eslint-plugin-ts': 2.11.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@stylistic/eslint-plugin-ts': 2.11.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta))(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
common-tags: 1.8.2
eslint: 9.16.0(jiti@1.21.6)
eslint-config-prettier: 9.1.0(eslint@9.16.0(jiti@1.21.6))
eslint-plugin-jsonc: 2.18.2(eslint@9.16.0(jiti@1.21.6))
eslint-plugin-prettier: 5.2.1(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(prettier@3.4.1)
globals: 15.13.0
typescript-eslint: 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
typescript-eslint: 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
transitivePeerDependencies:
- '@eslint/json'
- '@types/eslint'
@@ -8092,22 +8092,22 @@ snapshots:
'@radix-ui/rect@1.1.0': {}
'@remix-run/cloudflare-pages@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)':
'@remix-run/cloudflare-pages@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)':
dependencies:
'@cloudflare/workers-types': 4.20241127.0
'@remix-run/cloudflare': 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)
'@remix-run/cloudflare': 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
'@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)':
'@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)':
dependencies:
'@cloudflare/kv-asset-handler': 0.1.3
'@cloudflare/workers-types': 4.20241127.0
'@remix-run/server-runtime': 2.15.0(typescript@5.7.2)
'@remix-run/server-runtime': 2.15.0(typescript@5.8.0-beta)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
'@remix-run/dev@2.15.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@types/node@22.10.1)(sass-embedded@1.81.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))(wrangler@3.91.0(@cloudflare/workers-types@4.20241127.0))':
'@remix-run/dev@2.15.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@types/node@22.10.1)(sass-embedded@1.81.0)(typescript@5.8.0-beta)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0))(wrangler@3.91.0(@cloudflare/workers-types@4.20241127.0))':
dependencies:
'@babel/core': 7.26.0
'@babel/generator': 7.26.2
@@ -8119,10 +8119,10 @@ snapshots:
'@babel/types': 7.26.0
'@mdx-js/mdx': 2.3.0
'@npmcli/package-json': 4.0.1
'@remix-run/node': 2.15.0(typescript@5.7.2)
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)
'@remix-run/node': 2.15.0(typescript@5.8.0-beta)
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta)
'@remix-run/router': 1.21.0
'@remix-run/server-runtime': 2.15.0(typescript@5.7.2)
'@remix-run/server-runtime': 2.15.0(typescript@5.8.0-beta)
'@types/mdx': 2.0.13
'@vanilla-extract/integration': 6.5.0(@types/node@22.10.1)(sass-embedded@1.81.0)
arg: 5.0.2
@@ -8162,11 +8162,11 @@ snapshots:
set-cookie-parser: 2.7.1
tar-fs: 2.1.1
tsconfig-paths: 4.2.0
valibot: 0.41.0(typescript@5.7.2)
valibot: 0.41.0(typescript@5.8.0-beta)
vite-node: 1.6.0(@types/node@22.10.1)(sass-embedded@1.81.0)
ws: 7.5.10
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
vite: 5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)
wrangler: 3.91.0(@cloudflare/workers-types@4.20241127.0)
transitivePeerDependencies:
@@ -8185,9 +8185,9 @@ snapshots:
- ts-node
- utf-8-validate
'@remix-run/node@2.15.0(typescript@5.7.2)':
'@remix-run/node@2.15.0(typescript@5.8.0-beta)':
dependencies:
'@remix-run/server-runtime': 2.15.0(typescript@5.7.2)
'@remix-run/server-runtime': 2.15.0(typescript@5.8.0-beta)
'@remix-run/web-fetch': 4.4.2
'@web3-storage/multipart-parser': 1.0.0
cookie-signature: 1.2.2
@@ -8195,23 +8195,23 @@ snapshots:
stream-slice: 0.1.2
undici: 6.21.0
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
'@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)':
'@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta)':
dependencies:
'@remix-run/router': 1.21.0
'@remix-run/server-runtime': 2.15.0(typescript@5.7.2)
'@remix-run/server-runtime': 2.15.0(typescript@5.8.0-beta)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-router: 6.28.0(react@18.3.1)
react-router-dom: 6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
turbo-stream: 2.4.0
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
'@remix-run/router@1.21.0': {}
'@remix-run/server-runtime@2.15.0(typescript@5.7.2)':
'@remix-run/server-runtime@2.15.0(typescript@5.8.0-beta)':
dependencies:
'@remix-run/router': 1.21.0
'@types/cookie': 0.6.0
@@ -8221,7 +8221,7 @@ snapshots:
source-map: 0.7.4
turbo-stream: 2.4.0
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
'@remix-run/web-blob@3.1.0':
dependencies:
@@ -8645,9 +8645,9 @@ snapshots:
'@smithy/util-buffer-from': 3.0.0
tslib: 2.8.1
'@stylistic/eslint-plugin-ts@2.11.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)':
'@stylistic/eslint-plugin-ts@2.11.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)':
dependencies:
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
eslint: 9.16.0(jiti@1.21.6)
eslint-visitor-keys: 4.2.0
espree: 10.3.0
@@ -8747,34 +8747,34 @@ snapshots:
'@types/uuid@9.0.8': {}
'@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)':
'@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta))(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/visitor-keys': 8.17.0
eslint: 9.16.0(jiti@1.21.6)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
ts-api-utils: 1.4.3(typescript@5.7.2)
ts-api-utils: 1.4.3(typescript@5.8.0-beta)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)':
'@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)':
dependencies:
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.8.0-beta)
'@typescript-eslint/visitor-keys': 8.17.0
debug: 4.3.7
eslint: 9.16.0(jiti@1.21.6)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
@@ -8783,21 +8783,21 @@ snapshots:
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/visitor-keys': 8.17.0
'@typescript-eslint/type-utils@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)':
'@typescript-eslint/type-utils@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)':
dependencies:
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.8.0-beta)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
debug: 4.3.7
eslint: 9.16.0(jiti@1.21.6)
ts-api-utils: 1.4.3(typescript@5.7.2)
ts-api-utils: 1.4.3(typescript@5.8.0-beta)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.17.0': {}
'@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)':
'@typescript-eslint/typescript-estree@8.17.0(typescript@5.8.0-beta)':
dependencies:
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/visitor-keys': 8.17.0
@@ -8806,21 +8806,21 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.6.3
ts-api-utils: 1.4.3(typescript@5.7.2)
ts-api-utils: 1.4.3(typescript@5.8.0-beta)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)':
'@typescript-eslint/utils@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.16.0(jiti@1.21.6))
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.8.0-beta)
eslint: 9.16.0(jiti@1.21.6)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
@@ -9099,7 +9099,7 @@ snapshots:
'@web3-storage/multipart-parser@1.0.0': {}
'@webcontainer/api@1.3.0-internal.10': {}
'@webcontainer/api@1.5.1-internal.8': {}
'@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)':
dependencies:
@@ -12193,20 +12193,20 @@ snapshots:
mdast-util-to-markdown: 2.1.2
unified: 11.0.5
remix-island@0.2.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/server-runtime@2.15.0(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
remix-island@0.2.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@remix-run/server-runtime@2.15.0(typescript@5.8.0-beta))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)
'@remix-run/server-runtime': 2.15.0(typescript@5.7.2)
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta)
'@remix-run/server-runtime': 2.15.0(typescript@5.8.0-beta)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
remix-utils@7.7.0(@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2))(@remix-run/node@2.15.0(typescript@5.7.2))(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.23.8):
remix-utils@7.7.0(@remix-run/cloudflare@2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta))(@remix-run/node@2.15.0(typescript@5.8.0-beta))(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta))(@remix-run/router@1.21.0)(react@18.3.1)(zod@3.23.8):
dependencies:
type-fest: 4.30.0
optionalDependencies:
'@remix-run/cloudflare': 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.7.2)
'@remix-run/node': 2.15.0(typescript@5.7.2)
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)
'@remix-run/cloudflare': 2.15.0(@cloudflare/workers-types@4.20241127.0)(typescript@5.8.0-beta)
'@remix-run/node': 2.15.0(typescript@5.8.0-beta)
'@remix-run/react': 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.0-beta)
'@remix-run/router': 1.21.0
react: 18.3.1
zod: 3.23.8
@@ -12702,13 +12702,13 @@ snapshots:
trough@2.2.0: {}
ts-api-utils@1.4.3(typescript@5.7.2):
ts-api-utils@1.4.3(typescript@5.8.0-beta):
dependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
tsconfck@3.1.4(typescript@5.7.2):
tsconfck@3.1.4(typescript@5.8.0-beta):
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
tsconfig-paths@4.2.0:
dependencies:
@@ -12740,18 +12740,18 @@ snapshots:
media-typer: 0.3.0
mime-types: 2.1.35
typescript-eslint@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2):
typescript-eslint@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta):
dependencies:
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta))(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
'@typescript-eslint/utils': 8.17.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.8.0-beta)
eslint: 9.16.0(jiti@1.21.6)
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
transitivePeerDependencies:
- supports-color
typescript@5.7.2: {}
typescript@5.8.0-beta: {}
ufo@1.5.4: {}
@@ -12955,9 +12955,9 @@ snapshots:
kleur: 4.1.5
sade: 1.8.1
valibot@0.41.0(typescript@5.7.2):
valibot@0.41.0(typescript@5.8.0-beta):
optionalDependencies:
typescript: 5.7.2
typescript: 5.8.0-beta
validate-npm-package-license@3.0.4:
dependencies:
@@ -13047,11 +13047,11 @@ snapshots:
dependencies:
vite: 5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)
vite-tsconfig-paths@4.3.2(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)):
vite-tsconfig-paths@4.3.2(typescript@5.8.0-beta)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)):
dependencies:
debug: 4.3.7
globrex: 0.1.2
tsconfck: 3.1.4(typescript@5.7.2)
tsconfck: 3.1.4(typescript@5.8.0-beta)
optionalDependencies:
vite: 5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)
transitivePeerDependencies: