mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-15 17:16:16 +08:00
feat(core): mode in query string (#7904)
This commit is contained in:
@@ -81,6 +81,7 @@
|
||||
"mixpanel-browser": "^2.49.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"next-themes": "^0.3.0",
|
||||
"query-string": "^9.1.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Entity, LiveData } from '@toeverything/infra';
|
||||
import type { Location, To } from 'history';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import queryString from 'query-string';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { createNavigableHistory } from '../../../utils/navigable-history';
|
||||
@@ -77,6 +79,52 @@ export class View extends Entity<{
|
||||
|
||||
icon$ = new LiveData(this.props.icon ?? 'allDocs');
|
||||
|
||||
queryString$<T extends Record<string, unknown>>({
|
||||
parseNumbers = true,
|
||||
}: { parseNumbers?: boolean } = {}) {
|
||||
return this.location$.map(
|
||||
location =>
|
||||
queryString.parse(location.search, {
|
||||
parseBooleans: true,
|
||||
parseNumbers: parseNumbers,
|
||||
}) as Partial<T>
|
||||
);
|
||||
}
|
||||
|
||||
updateQueryString<T extends Record<string, unknown>>(
|
||||
patch: Partial<T>,
|
||||
{
|
||||
forceUpdate,
|
||||
parseNumbers,
|
||||
replace,
|
||||
}: {
|
||||
forceUpdate?: boolean;
|
||||
parseNumbers?: boolean;
|
||||
replace?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
const oldQueryStrings = queryString.parse(location.search, {
|
||||
parseBooleans: true,
|
||||
parseNumbers: parseNumbers,
|
||||
});
|
||||
const newQueryStrings = { ...oldQueryStrings, ...patch };
|
||||
|
||||
if (forceUpdate || !isEqual(oldQueryStrings, newQueryStrings)) {
|
||||
const search = queryString.stringify(newQueryStrings);
|
||||
|
||||
const newState = {
|
||||
...this.history.location,
|
||||
search,
|
||||
};
|
||||
|
||||
if (replace) {
|
||||
this.history.replace(newState);
|
||||
} else {
|
||||
this.history.push(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push(path: To) {
|
||||
this.history.push(path);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { Editor } from '@affine/core/modules/editor';
|
||||
import { EditorService, EditorsService } from '@affine/core/modules/editor';
|
||||
import { RecentDocsService } from '@affine/core/modules/quicksearch';
|
||||
import { ViewService } from '@affine/core/modules/workbench/services/view';
|
||||
import type { PageRootService } from '@blocksuite/blocks';
|
||||
import type { DocMode, PageRootService } from '@blocksuite/blocks';
|
||||
import {
|
||||
BookmarkBlockService,
|
||||
customImageProxyMiddleware,
|
||||
@@ -330,9 +330,25 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
|
||||
const docRecordList = docsService.list;
|
||||
const docListReady = useLiveData(docRecordList.isReady$);
|
||||
const docRecord = useLiveData(docRecordList.doc$(pageId));
|
||||
const viewService = useService(ViewService);
|
||||
|
||||
const queryString = useLiveData(
|
||||
viewService.view.queryString$<{
|
||||
mode?: string;
|
||||
}>()
|
||||
);
|
||||
|
||||
const queryStringMode =
|
||||
queryString.mode && ['edgeless', 'page'].includes(queryString.mode)
|
||||
? (queryString.mode as DocMode)
|
||||
: null;
|
||||
|
||||
// We only read the querystring mode when entering, so use useState here.
|
||||
const [initialQueryStringMode] = useState(() => queryStringMode);
|
||||
|
||||
const [doc, setDoc] = useState<Doc | null>(null);
|
||||
const [editor, setEditor] = useState<Editor | null>(null);
|
||||
const editorMode = useLiveData(editor?.mode$);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!docRecord) {
|
||||
@@ -351,12 +367,26 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
|
||||
}
|
||||
const editor = doc.scope
|
||||
.get(EditorsService)
|
||||
.createEditor(doc.getPrimaryMode() || 'page');
|
||||
.createEditor(initialQueryStringMode || doc.getPrimaryMode() || 'page');
|
||||
setEditor(editor);
|
||||
return () => {
|
||||
editor.dispose();
|
||||
};
|
||||
}, [doc]);
|
||||
}, [doc, initialQueryStringMode]);
|
||||
|
||||
// update editor mode to queryString
|
||||
useEffect(() => {
|
||||
if (editorMode) {
|
||||
viewService.view.updateQueryString(
|
||||
{
|
||||
mode: editorMode,
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}, [editorMode, viewService.view]);
|
||||
|
||||
// set sync engine priority target
|
||||
useEffect(() => {
|
||||
|
||||
@@ -310,6 +310,7 @@ export enum ErrorNames {
|
||||
MAILER_SERVICE_IS_NOT_CONFIGURED = 'MAILER_SERVICE_IS_NOT_CONFIGURED',
|
||||
MEMBER_QUOTA_EXCEEDED = 'MEMBER_QUOTA_EXCEEDED',
|
||||
MISSING_OAUTH_QUERY_PARAMETER = 'MISSING_OAUTH_QUERY_PARAMETER',
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
NOT_IN_WORKSPACE = 'NOT_IN_WORKSPACE',
|
||||
NO_COPILOT_PROVIDER_AVAILABLE = 'NO_COPILOT_PROVIDER_AVAILABLE',
|
||||
OAUTH_ACCOUNT_ALREADY_CONNECTED = 'OAUTH_ACCOUNT_ALREADY_CONNECTED',
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
filterTags,
|
||||
removeSelectedTag,
|
||||
} from '@affine-test/kit/utils/properties';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect, type Page } from '@playwright/test';
|
||||
|
||||
const searchAndCreateTag = async (page: Page, name: string) => {
|
||||
@@ -64,7 +65,7 @@ test('New a page and open it ,then open info modal in the title bar more action
|
||||
});
|
||||
|
||||
test('New a page, then open info modal from all doc', async ({ page }) => {
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = getPageByTitle(page, 'this is a new page');
|
||||
@@ -83,7 +84,7 @@ test('New a page, then open info modal from all doc', async ({ page }) => {
|
||||
test('New a page and add to favourites, then open info modal from sidebar', async ({
|
||||
page,
|
||||
}) => {
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
await clickPageMoreActions(page);
|
||||
await page.getByTestId('editor-option-menu-favorite').click();
|
||||
|
||||
@@ -8,6 +8,10 @@ import {
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import {
|
||||
getCurrentCollectionIdFromUrl,
|
||||
getCurrentDocIdFromUrl,
|
||||
} from '@affine-test/kit/utils/url';
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
@@ -32,7 +36,7 @@ const createCollection = async (page: Page, name: string) => {
|
||||
await expect(input).toBeVisible();
|
||||
await input.fill(name);
|
||||
await page.getByTestId('save-collection').click();
|
||||
const newCollectionId = page.url().split('/').reverse()[0];
|
||||
const newCollectionId = getCurrentCollectionIdFromUrl(page);
|
||||
const collection = page.getByTestId(`explorer-collection-${newCollectionId}`);
|
||||
await expect(collection).toBeVisible();
|
||||
return collection;
|
||||
@@ -85,7 +89,7 @@ test('drag a page from "All pages" list to favourites, then drag to trash', asyn
|
||||
const title = 'this is a new page to drag';
|
||||
await waitForEditorLoad(page);
|
||||
await createPage(page, title);
|
||||
const pageId = page.url().split('/').reverse()[0];
|
||||
const pageId = getCurrentDocIdFromUrl(page);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
@@ -133,7 +137,7 @@ test('drag a page from favourites to collection', async ({ page }) => {
|
||||
const title = 'this is a new page to drag';
|
||||
await createPage(page, title);
|
||||
|
||||
const pageId = page.url().split('/').reverse()[0];
|
||||
const pageId = getCurrentDocIdFromUrl(page);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
@@ -152,7 +156,7 @@ test('drag a collection to favourites', async ({ page }) => {
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
const collection = await createCollection(page, 'test collection');
|
||||
const collectionId = page.url().split('/').reverse()[0];
|
||||
const collectionId = getCurrentCollectionIdFromUrl(page);
|
||||
await dragToFavourites(page, collection, collectionId, 'collection');
|
||||
});
|
||||
|
||||
@@ -167,7 +171,7 @@ test('items in favourites can be reordered by dragging', async ({ page }) => {
|
||||
|
||||
{
|
||||
const collection = await createCollection(page, 'test collection');
|
||||
const collectionId = page.url().split('/').reverse()[0];
|
||||
const collectionId = getCurrentCollectionIdFromUrl(page);
|
||||
await dragToFavourites(page, collection, collectionId, 'collection');
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('page delete -> refresh page -> it should be disappear', async ({
|
||||
@@ -18,7 +19,7 @@ test('page delete -> refresh page -> it should be disappear', async ({
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page delete');
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page.getByRole('cell', {
|
||||
name: 'this is a new page delete',
|
||||
@@ -54,7 +55,7 @@ test('page delete -> create new page -> refresh page -> new page should be appea
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page delete');
|
||||
const newPageDeleteId = page.url().split('/').reverse()[0];
|
||||
const newPageDeleteId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cellDelete = page.getByRole('cell', {
|
||||
name: 'this is a new page delete',
|
||||
@@ -80,13 +81,13 @@ test('page delete -> create new page -> refresh page -> new page should be appea
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page1');
|
||||
await page.waitForTimeout(1000);
|
||||
const newPageId1 = page.url().split('/').reverse()[0];
|
||||
const newPageId1 = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page2');
|
||||
await page.waitForTimeout(1000);
|
||||
const newPageId2 = page.url().split('/').reverse()[0];
|
||||
const newPageId2 = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
await page.reload();
|
||||
await getPageItem(page, newPageId1).click();
|
||||
@@ -109,13 +110,13 @@ test('delete multiple pages -> create multiple pages -> refresh', async ({
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page1');
|
||||
const newPageId1 = page.url().split('/').reverse()[0];
|
||||
const newPageId1 = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
// create 2nd page
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page2');
|
||||
const newPageId2 = page.url().split('/').reverse()[0];
|
||||
const newPageId2 = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
// 1st cell to be deleted
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
waitForEditorLoad,
|
||||
waitForEmptyEditor,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('Show favorite items in sidebar', async ({ page, workspace }) => {
|
||||
@@ -18,7 +19,7 @@ test('Show favorite items in sidebar', async ({ page, workspace }) => {
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = getPageByTitle(page, 'this is a new page to favorite');
|
||||
await expect(cell).toBeVisible();
|
||||
@@ -50,7 +51,7 @@ test('Show favorite reference in sidebar', async ({ page, workspace }) => {
|
||||
|
||||
await createLinkedPage(page, 'Another page');
|
||||
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
await clickPageMoreActions(page);
|
||||
|
||||
@@ -89,7 +90,7 @@ test("Deleted page's reference will not be shown in sidebar", async ({
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
|
||||
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
// goes to main content
|
||||
await page.keyboard.press('Enter', { delay: 50 });
|
||||
@@ -108,7 +109,7 @@ test("Deleted page's reference will not be shown in sidebar", async ({
|
||||
page.locator('.doc-title-container:has-text("Another page")')
|
||||
).toBeVisible();
|
||||
|
||||
const anotherPageId = page.url().split('/').reverse()[0];
|
||||
const anotherPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
const favItemTestId = 'explorer-doc-' + newPageId;
|
||||
|
||||
|
||||
@@ -5,14 +5,15 @@ import {
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('click btn new page', async ({ page, workspace }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
const originPageId = page.url().split('/').reverse()[0];
|
||||
const originPageId = getCurrentDocIdFromUrl(page);
|
||||
await clickNewPageButton(page);
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
expect(newPageId).not.toBe(originPageId);
|
||||
const currentWorkspace = await workspace.current();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('click btn new page and open in tab', async ({ page, workspace }) => {
|
||||
@@ -15,7 +16,7 @@ test('click btn new page and open in tab', async ({ page, workspace }) => {
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page');
|
||||
const newPageUrl = page.url();
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('New a page , then delete it in all pages, restore it', async ({
|
||||
@@ -17,7 +18,7 @@ test('New a page , then delete it in all pages, restore it', async ({
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to restore');
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page.getByRole('cell', {
|
||||
name: 'this is a new page to restore',
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('New a page ,then open it and show delete modal', async ({
|
||||
@@ -44,7 +45,7 @@ test('New a page ,then go to all pages and show delete modal', async ({
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page.getByRole('cell', {
|
||||
name: 'this is a new page to delete',
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('New a page , then delete it in all pages, finally find it in trash', async ({
|
||||
@@ -17,7 +18,7 @@ test('New a page , then delete it in all pages, finally find it in trash', async
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
|
||||
const newPageId = page.url().split('/').reverse()[0];
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page.getByRole('cell', {
|
||||
name: 'this is a new page to delete',
|
||||
|
||||
@@ -6,9 +6,10 @@ import { expect } from '@playwright/test';
|
||||
test('goto not found page', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
const currentUrl = page.url();
|
||||
const invalidUrl = currentUrl.concat('invalid');
|
||||
await page.goto(invalidUrl);
|
||||
const currentUrl = new URL(page.url());
|
||||
const invalidUrl = (currentUrl.pathname =
|
||||
currentUrl.pathname.concat('invalid'));
|
||||
await page.goto(invalidUrl.toString());
|
||||
await expect(page.getByTestId('not-found')).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
export function getCurrentDocIdFromUrl(page: Page) {
|
||||
const pathname = new URL(page.url()).pathname;
|
||||
const match = pathname.match(/\/workspace\/([^/]+)\/([^/]+)\/?/);
|
||||
if (match && match[2]) {
|
||||
return match[2];
|
||||
}
|
||||
throw new Error('Failed to get doc id from url');
|
||||
}
|
||||
|
||||
export function getCurrentCollectionIdFromUrl(page: Page) {
|
||||
const pathname = new URL(page.url()).pathname;
|
||||
const match = pathname.match(/\/workspace\/([^/]+)\/collection\/([^/]+)\/?/);
|
||||
if (match && match[2]) {
|
||||
return match[2];
|
||||
}
|
||||
throw new Error('Failed to get collection id from url');
|
||||
}
|
||||
@@ -464,6 +464,7 @@ __metadata:
|
||||
mixpanel-browser: "npm:^2.49.0"
|
||||
nanoid: "npm:^5.0.7"
|
||||
next-themes: "npm:^0.3.0"
|
||||
query-string: "npm:^9.1.0"
|
||||
react: "npm:18.3.1"
|
||||
react-dom: "npm:18.3.1"
|
||||
react-error-boundary: "npm:^4.0.13"
|
||||
@@ -20679,6 +20680,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"decode-uri-component@npm:^0.4.1":
|
||||
version: 0.4.1
|
||||
resolution: "decode-uri-component@npm:0.4.1"
|
||||
checksum: 10/74eec26f7bec3767164e37d526ef19bc1214cb0bbeeeea1c4f0ceb79299e5c38d3ba734e7243d829842aa140f24e5d020f54cc25b17c7082461c8eead8a72ce3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"decompress-response@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "decompress-response@npm:6.0.0"
|
||||
@@ -23414,6 +23422,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"filter-obj@npm:^5.1.0":
|
||||
version: 5.1.0
|
||||
resolution: "filter-obj@npm:5.1.0"
|
||||
checksum: 10/8f6dab6d8d8855f686e8cc6be289bbbd64a80be52c660124e36e982f78017cf5dae7de95f79ec167fbf62101d6aab93067a3105ae8f56251785a721e678d6b07
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"finalhandler@npm:1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "finalhandler@npm:1.2.0"
|
||||
@@ -32984,6 +32999,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"query-string@npm:^9.1.0":
|
||||
version: 9.1.0
|
||||
resolution: "query-string@npm:9.1.0"
|
||||
dependencies:
|
||||
decode-uri-component: "npm:^0.4.1"
|
||||
filter-obj: "npm:^5.1.0"
|
||||
split-on-first: "npm:^3.0.0"
|
||||
checksum: 10/87a0ea851f62d6abe5c6c60bc0114e5df1af73f6dbdfd3086ab82624330cafe92310029d834ee6117d92e3de877f2959cb634c31a55a1aef4acddaa11ad8be20
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"querystring@npm:0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "querystring@npm:0.2.0"
|
||||
@@ -35446,6 +35472,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"split-on-first@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "split-on-first@npm:3.0.0"
|
||||
checksum: 10/75dc27ecbac65cfbeab9a3b90cf046307220192d3d7a30e46aa0f19571cc9b4802aac813f3de2cc9b16f2e46aae72f275659b5d2614bb5369c77724d739e5f73
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"split2@npm:^4.0.0":
|
||||
version: 4.2.0
|
||||
resolution: "split2@npm:4.2.0"
|
||||
|
||||
Reference in New Issue
Block a user