From 16ce80bb4cbf211f4986c641a8e12bf380229465 Mon Sep 17 00:00:00 2001 From: Rafael Velazco Date: Wed, 30 Oct 2024 17:14:28 -0400 Subject: [PATCH 01/11] feat(Examples): Unable to Edit Unpublished Page (#30470) This pull request includes several key updates to the `core-web` and `examples` directories, focusing on improving component behavior, enhancing testing, and refining error handling. ### Component Behavior Improvements: * [`core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts`](diffhunk://#diff-24dc496db1eb6feb3e10a031baa4b4b63c20f1cd02ade574065f6b967f11c365R530): Updated `ngOnDestroy` method to set `isClientReady` to `false` when the component is destroyed. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts`](diffhunk://#diff-34ddc5fbacaf04b962f2037385ed284310d5faf35ba409d5705b2caadd5d796aR461-R468): Added a test to ensure `isClientReady` is set to `false` upon component destruction. ### Testing Enhancements: * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/withLayout.spec.ts`](diffhunk://#diff-c4b441749ccd043be6d95340a54fbc26c7466acfc6e2d4ae4672f043170f7008R1-R77): Added comprehensive tests for the `withLayout` feature, including layout properties and update methods. * [`core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts`](diffhunk://#diff-cdf3dddb12d973780196e0402f92c62736024ca9fc5b5b649f104565849d4d0eR1-R354): Introduced tests for the `withLoad` feature, covering store initialization, navigation, and error handling. ### Error Handling and Code Cleanup: * [`examples/angular/src/app/pages/services/page.service.ts`](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L30-R52): Enhanced error handling in `fetchPage` method and improved the structure of the `getPageAndNavigation` method to use `forkJoin` for concurrent requests. ([examples/angular/src/app/pages/services/page.service.tsL30-R52](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L30-R52), F6efbd08L65R84) * [`examples/angular/src/app/pages/pages.component.ts`](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L75-R102): Refactored the `ngOnInit` method for better readability and added a console log for debugging in `#setError` method. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L75-R102) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395R114-R116) ### Minor Code Cleanups: * [`examples/angular/src/app/pages/pages.component.ts`](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L1-R1): Removed unnecessary line breaks and simplified import statements. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L1-R1) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L41) * [`examples/astro/src/components/Error.astro`](diffhunk://#diff-e67728dc39a0c654337d1f78dffb4b1edabfb1cbb0b24d4047c75bc4c4702971L3-L4): Removed unused variables and cleaned up the code. ### Video https://github.com/user-attachments/assets/426ef750-b367-4e05-beda-37ea44e87f66 --- .../edit-ema-editor.component.spec.ts | 8 + .../edit-ema-editor.component.ts | 1 + .../src/lib/store/dot-uve.store.spec.ts | 1259 +---------------- .../store/features/editor/withEditor.spec.ts | 1077 ++++++++++++++ .../store/features/layout/wihtLayout.spec.ts | 77 + .../lib/store/features/load/withLoad.spec.ts | 354 +++++ .../angular/src/app/pages/pages.component.ts | 50 +- .../src/app/pages/services/page.service.ts | 77 +- examples/astro/src/components/Error.astro | 32 +- .../astro/src/react/components/notFound.tsx | 27 + .../astro/src/react/hooks/usePageAsset.ts | 18 +- examples/astro/src/react/myPage.tsx | 6 + examples/astro/src/utils/client.ts | 44 +- examples/astro/tsconfig.json | 1 + examples/nextjs/src/app/[[...slug]]/page.js | 42 +- examples/nextjs/src/components/my-page.js | 24 +- examples/nextjs/src/hooks/usePageAsset.js | 20 +- examples/nextjs/src/utils/page.utils.js | 32 + 18 files changed, 1762 insertions(+), 1387 deletions(-) create mode 100644 core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts create mode 100644 core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts create mode 100644 core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts create mode 100644 examples/astro/src/react/components/notFound.tsx create mode 100644 examples/nextjs/src/utils/page.utils.js diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts index bf4f48df15cf..4a3812a0288a 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts @@ -458,6 +458,14 @@ describe('EditEmaEditorComponent', () => { ).not.toBeNull(); }); }); + + it('should set the client is ready to false when the component is destroyed', () => { + store.setIsClientReady(true); + + spectator.component.ngOnDestroy(); + + expect(store.isClientReady()).toBe(false); + }); }); describe('customer actions', () => { diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 0e935438362c..0f826f06f5e5 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -527,6 +527,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.destroy$.next(true); this.destroy$.complete(); + this.uveStore.setIsClientReady(false); } /** diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.spec.ts index 70fa254205b7..c7297b633cd6 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.spec.ts @@ -8,7 +8,7 @@ import { import { patchState } from '@ngrx/signals'; import { of } from 'rxjs'; -import { ActivatedRoute, ActivatedRouteSnapshot, ParamMap, Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { MessageService } from 'primeng/api'; @@ -18,8 +18,7 @@ import { DotLicenseService, DotMessageService } from '@dotcms/data-access'; -import { CurrentUser, LoginService } from '@dotcms/dotcms-js'; -import { DEFAULT_VARIANT_ID, DEFAULT_VARIANT_NAME, DotCMSContentlet } from '@dotcms/dotcms-models'; +import { LoginService } from '@dotcms/dotcms-js'; import { MockDotMessageService, getRunningExperimentMock, @@ -27,38 +26,22 @@ import { getDraftExperimentMock, DotLanguagesServiceMock, CurrentUserDataMock, - mockLanguageArray, - mockDotDevices, - seoOGTagsMock + mockLanguageArray } from '@dotcms/utils-testing'; import { UVEStore } from './dot-uve.store'; -import { DotPageApiResponse, DotPageApiService } from '../services/dot-page-api.service'; -import { BASE_IFRAME_MEASURE_UNIT, COMMON_ERRORS, DEFAULT_PERSONA } from '../shared/consts'; -import { EDITOR_STATE, UVE_STATUS } from '../shared/enums'; +import { DotPageApiService } from '../services/dot-page-api.service'; +import { COMMON_ERRORS } from '../shared/consts'; +import { UVE_STATUS } from '../shared/enums'; import { - ACTION_MOCK, - ACTION_PAYLOAD_MOCK, BASE_SHELL_ITEMS, BASE_SHELL_PROPS_RESPONSE, - EMA_DRAG_ITEM_CONTENTLET_MOCK, - getBoundsMock, - getVanityUrl, HEADLESS_BASE_QUERY_PARAMS, - MOCK_CONTENTLET_AREA, MOCK_RESPONSE_HEADLESS, MOCK_RESPONSE_VTL, - PERMANENT_REDIRECT_VANITY_URL, - TEMPORARY_REDIRECT_VANITY_URL, VTL_BASE_QUERY_PARAMS } from '../shared/mocks'; -import { DotDeviceWithIcon } from '../shared/models'; -import { - getPersonalization, - mapContainerStructureToArrayOfContainers, - mapContainerStructureToDotContainerMap -} from '../utils'; const buildPageAPIResponseFromMock = (mock) => @@ -70,28 +53,11 @@ const buildPageAPIResponseFromMock = pageURI: url } }); -const mockCurrentUser: CurrentUser = { - email: 'admin@dotcms.com', - givenName: 'Admin', - loginAs: true, - roleId: 'e7d4e34e-5127-45fc-8123-d48b62d510e3', - surname: 'User', - userId: 'dotcms.org.1' -}; -const mockOtherUser: CurrentUser = { - email: 'admin2@dotcms.com', - givenName: 'Admin2', - loginAs: true, - roleId: '73ec980e-d74f-4cec-a4d0-e319061e20b9', - surname: 'User', - userId: 'dotcms.org.2808' -}; + describe('UVEStore', () => { let spectator: SpectatorService>; let store: InstanceType; let dotPageApiService: SpyObject; - let activatedRoute: SpyObject; - let router: SpyObject; const createService = createServiceFactory({ service: UVEStore, @@ -153,8 +119,6 @@ describe('UVEStore', () => { store = spectator.service; dotPageApiService = spectator.inject(DotPageApiService); - router = spectator.inject(Router); - activatedRoute = spectator.inject(ActivatedRoute); jest.spyOn(dotPageApiService, 'get').mockImplementation( buildPageAPIResponseFromMock(MOCK_RESPONSE_HEADLESS) ); @@ -399,1213 +363,4 @@ describe('UVEStore', () => { }); }); }); - - describe('withLoad', () => { - describe('withMethods', () => { - it('should load the store with the base data', () => { - expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_HEADLESS); - expect(store.isEnterprise()).toBe(true); - expect(store.currentUser()).toEqual(CurrentUserDataMock); - expect(store.experiment()).toBe(undefined); - expect(store.languages()).toBe(mockLanguageArray); - expect(store.params()).toEqual(HEADLESS_BASE_QUERY_PARAMS); - expect(store.canEditPage()).toBe(true); - expect(store.pageIsLocked()).toBe(false); - expect(store.status()).toBe(UVE_STATUS.LOADED); - expect(store.isTraditionalPage()).toBe(false); - expect(store.isClientReady()).toBe(false); - }); - - it('should load the store with the base data for traditional page', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation( - buildPageAPIResponseFromMock(MOCK_RESPONSE_VTL) - ); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_VTL); - expect(store.isEnterprise()).toBe(true); - expect(store.currentUser()).toEqual(CurrentUserDataMock); - expect(store.experiment()).toBe(undefined); - expect(store.languages()).toBe(mockLanguageArray); - expect(store.params()).toEqual(VTL_BASE_QUERY_PARAMS); - expect(store.canEditPage()).toBe(true); - expect(store.pageIsLocked()).toBe(false); - expect(store.status()).toBe(UVE_STATUS.LOADED); - expect(store.isTraditionalPage()).toBe(true); - expect(store.isClientReady()).toBe(true); - }); - - it('should navigate when the page is a vanityUrl permanent redirect', () => { - const permanentRedirect = getVanityUrl( - VTL_BASE_QUERY_PARAMS.url, - PERMANENT_REDIRECT_VANITY_URL - ) as unknown as DotPageApiResponse; - - const forwardTo = PERMANENT_REDIRECT_VANITY_URL.forwardTo; - - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of(permanentRedirect) - ); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).toHaveBeenCalledWith([], { - queryParams: { - ...VTL_BASE_QUERY_PARAMS, - url: forwardTo - }, - queryParamsHandling: 'merge' - }); - }); - - it('should navigate when the page is a vanityUrl temporary redirect', () => { - const temporaryRedirect = getVanityUrl( - VTL_BASE_QUERY_PARAMS.url, - TEMPORARY_REDIRECT_VANITY_URL - ) as unknown as DotPageApiResponse; - - const forwardTo = TEMPORARY_REDIRECT_VANITY_URL.forwardTo; - - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of(temporaryRedirect) - ); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).toHaveBeenCalledWith([], { - queryParams: { - ...VTL_BASE_QUERY_PARAMS, - url: forwardTo - }, - queryParamsHandling: 'merge' - }); - }); - - it('should navigate to content when the layout is disable by page.canEdit and current route is layout', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of({ - ...MOCK_RESPONSE_VTL, - page: { - ...MOCK_RESPONSE_VTL.page, - canEdit: false - } - }) - ); - - jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ - snapshot: { - url: [ - { - path: 'layout', - parameters: {}, - parameterMap: {} as unknown as ParamMap - } - ] - } as unknown as ActivatedRouteSnapshot - } as unknown as ActivatedRoute); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).toHaveBeenCalledWith(['edit-page/content'], { - queryParamsHandling: 'merge' - }); - }); - - it('should navigate to content when the layout is disable by template.drawed and current route is layout', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of({ - ...MOCK_RESPONSE_VTL, - template: { - ...MOCK_RESPONSE_VTL.template, - drawed: false - } - }) - ); - - jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ - snapshot: { - url: [ - { - path: 'layout', - parameters: {}, - parameterMap: {} as unknown as ParamMap - } - ] - } as unknown as ActivatedRouteSnapshot - } as unknown as ActivatedRoute); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).toHaveBeenCalledWith(['edit-page/content'], { - queryParamsHandling: 'merge' - }); - }); - - it('should not navigate to content when the layout is disable by template.drawed and current route is not layout', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of({ - ...MOCK_RESPONSE_VTL, - template: { - ...MOCK_RESPONSE_VTL.template, - drawed: false - } - }) - ); - - jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ - snapshot: { - url: [ - { - path: 'rules', - parameters: {}, - parameterMap: {} as unknown as ParamMap - } - ] - } as unknown as ActivatedRouteSnapshot - } as unknown as ActivatedRoute); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).not.toHaveBeenCalled(); - }); - - it('should not navigate to content when the layout is disable by page.canEdit and current route is not layout', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation(() => - of({ - ...MOCK_RESPONSE_VTL, - page: { - ...MOCK_RESPONSE_VTL.page, - canEdit: false - } - }) - ); - - jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ - snapshot: { - url: [ - { - path: 'rules', - parameters: {}, - parameterMap: {} as unknown as ParamMap - } - ] - } as unknown as ActivatedRouteSnapshot - } as unknown as ActivatedRoute); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(router.navigate).not.toHaveBeenCalled(); - }); - - it('should reload the store with the same queryParams', () => { - const getPageSpy = jest.spyOn(dotPageApiService, 'get'); - - store.reload(); - - expect(getPageSpy).toHaveBeenCalledWith(store.params()); - }); - }); - }); - - describe('withLayout', () => { - describe('withComputed', () => { - describe('$layoutProps', () => { - it('should return the layout props', () => { - expect(store.$layoutProps()).toEqual({ - containersMap: mapContainerStructureToDotContainerMap( - MOCK_RESPONSE_HEADLESS.containers - ), - layout: MOCK_RESPONSE_HEADLESS.layout, - template: { - identifier: MOCK_RESPONSE_HEADLESS.template.identifier, - themeId: MOCK_RESPONSE_HEADLESS.template.theme, - anonymous: false - }, - pageId: MOCK_RESPONSE_HEADLESS.page.identifier - }); - }); - }); - }); - - describe('withMethods', () => { - it('should update the layout', () => { - const layout = { - ...MOCK_RESPONSE_HEADLESS.layout, - title: 'New layout' - }; - - store.updateLayout(layout); - - expect(store.pageAPIResponse().layout).toEqual(layout); - }); - }); - }); - - describe('withEditor', () => { - describe('withEditorToolbar', () => { - describe('withComputed', () => { - describe('$toolbarProps', () => { - it('should return the base info', () => { - expect(store.$toolbarProps()).toEqual({ - apiUrl: '/api/v1/page/json/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', - bookmarksUrl: '/test-url?host_id=123-xyz-567-xxl&language_id=1', - copyUrl: - 'http://localhost:3000/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&host_id=123-xyz-567-xxl', - currentLanguage: MOCK_RESPONSE_HEADLESS.viewAs.language, - deviceSelector: { - apiLink: - 'http://localhost:3000/api/v1/page/json/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', - hideSocialMedia: true - }, - personaSelector: { - pageId: MOCK_RESPONSE_HEADLESS.page.identifier, - value: MOCK_RESPONSE_HEADLESS.viewAs.persona ?? DEFAULT_PERSONA - }, - runningExperiment: null, - showInfoDisplay: false, - unlockButton: null, - urlContentMap: null, - workflowActionsInode: MOCK_RESPONSE_HEADLESS.page.inode - }); - }); - - describe('urlContentMap', () => { - it('should return the urlContentMap if the state is edit', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - urlContentMap: { - title: 'Title', - inode: '123', - contentType: 'test' - } as unknown as DotCMSContentlet - } - }); - - expect(store.$toolbarProps().urlContentMap).toEqual({ - title: 'Title', - inode: '123', - contentType: 'test' - }); - }); - - it('should not return the urlContentMap if the state is not edit', () => { - patchState(store, { isEditState: false }); - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - urlContentMap: { - title: 'Title', - inode: '123', - contentType: 'test' - } as unknown as DotCMSContentlet - } - }); - - expect(store.$toolbarProps().urlContentMap).toEqual(null); - }); - }); - - describe('runningExperiment', () => { - it('should have a runningExperiment if the experiment is running', () => { - patchState(store, { experiment: getRunningExperimentMock() }); - - expect(store.$toolbarProps().runningExperiment).toEqual( - getRunningExperimentMock() - ); - }); - }); - - describe('workflowActionsInode', () => { - it("should not have an workflowActionsInode if the user can't edit the page", () => { - patchState(store, { canEditPage: false }); - - expect(store.$toolbarProps().workflowActionsInode).toBe(null); - }); - }); - - describe('unlockButton', () => { - it('should display unlockButton if the page is locked by another user and the current user can lock the page', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - lockedBy: mockOtherUser.userId, - canLock: true - } - }, - currentUser: mockCurrentUser - }); - - expect(store.$toolbarProps().unlockButton).toEqual({ - inode: '123-i', - loading: false - }); - }); - - it('should not display unlockButton if the page is locked by the current user', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - lockedBy: mockCurrentUser.userId, - canLock: true - } - }, - currentUser: mockCurrentUser - }); - - expect(store.$toolbarProps().unlockButton).toBeNull(); - }); - - it('should not display unlockButton if the page is not locked', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: false, - canLock: true - } - }, - currentUser: mockCurrentUser - }); - - expect(store.$toolbarProps().unlockButton).toBeNull(); - }); - - it('should not display unlockButton if the user cannot lock the page', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - canLock: false - } - }, - currentUser: mockCurrentUser - }); - - expect(store.$toolbarProps().unlockButton).toBeNull(); - }); - }); - - describe('shouldShowInfoDisplay', () => { - it("should have shouldShowInfoDisplay as true if the user can't edit the page", () => { - patchState(store, { canEditPage: false }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(true); - }); - - it('should have shouldShowInfoDisplay as true if the device is set', () => { - patchState(store, { device: mockDotDevices[0] }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(true); - }); - - it('should have shouldShowInfoDisplay as true if the socialMedia is set', () => { - patchState(store, { socialMedia: 'facebook' }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(true); - }); - - it('should have shouldShowInfoDisplay as true if the page is a variant different from default', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - viewAs: { - ...MOCK_RESPONSE_HEADLESS.viewAs, - variantId: 'test' - } - } - }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(true); - }); - it('should have shouldShowInfoDisplay as true if the page is locked by another user', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - lockedBy: mockOtherUser.userId - } - }, - currentUser: mockCurrentUser - }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(true); - }); - - it('should have shouldShowInfoDisplay as false if the page is locked by the current user and other conditions are not met', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - lockedBy: mockCurrentUser.userId - } - }, - currentUser: mockCurrentUser, - canEditPage: true, - device: null, - socialMedia: null - }); - - expect(store.$toolbarProps().showInfoDisplay).toBe(false); - }); - }); - }); - - describe('$infoDisplayOptions', () => { - it('should be null in regular conditions', () => { - expect(store.$infoDisplayOptions()).toBe(null); - }); - - it('should return info for device', () => { - const device = mockDotDevices[0] as DotDeviceWithIcon; - - patchState(store, { device }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: device.icon, - info: { - message: 'iphone 200 x 100', - args: [] - }, - id: 'device', - actionIcon: 'pi pi-times' - }); - }); - - it('should return info for socialMedia', () => { - patchState(store, { socialMedia: 'Facebook' }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-facebook', - info: { - message: 'Viewing Facebook social media preview', - args: [] - }, - id: 'socialMedia', - actionIcon: 'pi pi-times' - }); - }); - - it('should return info when visiting a variant and can edit', () => { - const currentExperiment = getRunningExperimentMock(); - - const variantID = currentExperiment.trafficProportion.variants.find( - (variant) => variant.name !== DEFAULT_VARIANT_NAME - ).id; - - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - viewAs: { - ...MOCK_RESPONSE_HEADLESS.viewAs, - variantId: variantID - } - }, - experiment: currentExperiment - }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-file-edit', - info: { - message: 'editpage.editing.variant', - args: ['Variant A'] - }, - id: 'variant', - actionIcon: 'pi pi-arrow-left' - }); - }); - - it('should return info when visiting a variant and can not edit', () => { - const currentExperiment = getRunningExperimentMock(); - - const variantID = currentExperiment.trafficProportion.variants.find( - (variant) => variant.name !== DEFAULT_VARIANT_NAME - ).id; - - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page - }, - viewAs: { - ...MOCK_RESPONSE_HEADLESS.viewAs, - variantId: variantID - } - }, - experiment: currentExperiment, - canEditPage: false - }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-file-edit', - info: { - message: 'editpage.viewing.variant', - args: ['Variant A'] - }, - id: 'variant', - actionIcon: 'pi pi-arrow-left' - }); - }); - - it('should return info when the page is locked and can lock', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - canLock: true, - lockedByName: 'John Doe' - } - } - }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-lock', - info: { - message: 'editpage.locked-by', - args: ['John Doe'] - }, - id: 'locked' - }); - }); - - it('should return info when the page is locked and cannot lock', () => { - patchState(store, { - pageAPIResponse: { - ...MOCK_RESPONSE_HEADLESS, - page: { - ...MOCK_RESPONSE_HEADLESS.page, - locked: true, - canLock: false, - lockedByName: 'John Doe' - } - } - }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-lock', - info: { - message: 'editpage.locked-contact-with', - args: ['John Doe'] - }, - id: 'locked' - }); - }); - - it('should return info when you cannot edit the page', () => { - patchState(store, { canEditPage: false }); - - expect(store.$infoDisplayOptions()).toEqual({ - icon: 'pi pi-exclamation-circle warning', - info: { message: 'editema.dont.have.edit.permission', args: [] }, - id: 'no-permission' - }); - }); - }); - }); - - describe('withMethods', () => { - it('should set the device with setDevice', () => { - const device = { - identifier: '123', - cssHeight: '120', - cssWidth: '120', - name: 'square', - inode: '1234', - icon: 'icon' - }; - - store.setDevice(device); - - expect(store.device()).toEqual(device); - expect(store.isEditState()).toBe(false); - }); - - it('should set the socialMedia with setSocialMedia', () => { - const socialMedia = 'facebook'; - - store.setSocialMedia(socialMedia); - - expect(store.socialMedia()).toEqual(socialMedia); - expect(store.isEditState()).toBe(false); - }); - - it('should reset the state with clearDeviceAndSocialMedia', () => { - store.clearDeviceAndSocialMedia(); - - expect(store.device()).toBe(null); - expect(store.socialMedia()).toBe(null); - expect(store.isEditState()).toBe(true); - }); - }); - }); - - describe('withSave', () => { - describe('withMethods', () => { - describe('savePage', () => { - it('should perform a save and patch the state', () => { - const saveSpy = jest - .spyOn(dotPageApiService, 'save') - .mockImplementation(() => of({})); - - // It's impossible to get a VTL when we are in Headless - // but I just want to check the state is being patched - const getClientPageSpy = jest - .spyOn(dotPageApiService, 'getClientPage') - .mockImplementation(() => of(MOCK_RESPONSE_VTL)); - - const payload = { - pageContainers: ACTION_PAYLOAD_MOCK.pageContainers, - pageId: MOCK_RESPONSE_HEADLESS.page.identifier, - params: store.params() - }; - - store.savePage(ACTION_PAYLOAD_MOCK.pageContainers); - - expect(saveSpy).toHaveBeenCalledWith(payload); - - expect(getClientPageSpy).toHaveBeenCalledWith( - store.params(), - store.clientRequestProps() - ); - - expect(store.status()).toBe(UVE_STATUS.LOADED); - expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_VTL); - }); - }); - }); - }); - - describe('withComputed', () => { - describe('$pageData', () => { - it('should return the expected data', () => { - expect(store.$pageData()).toEqual({ - containers: mapContainerStructureToArrayOfContainers( - MOCK_RESPONSE_HEADLESS.containers - ), - id: MOCK_RESPONSE_HEADLESS.page.identifier, - personalization: getPersonalization(MOCK_RESPONSE_HEADLESS.viewAs.persona), - languageId: MOCK_RESPONSE_HEADLESS.viewAs.language.id, - personaTag: MOCK_RESPONSE_HEADLESS.viewAs.persona.keyTag - }); - }); - }); - - describe('$reloadEditorContent', () => { - it('should return the expected data for Headless', () => { - expect(store.$reloadEditorContent()).toEqual({ - code: MOCK_RESPONSE_HEADLESS.page.rendered, - isTraditionalPage: false, - enableInlineEdit: true, - isClientReady: false - }); - }); - it('should return the expected data for VTL', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation( - buildPageAPIResponseFromMock(MOCK_RESPONSE_VTL) - ); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(store.$reloadEditorContent()).toEqual({ - code: MOCK_RESPONSE_VTL.page.rendered, - isTraditionalPage: true, - enableInlineEdit: true, - isClientReady: true - }); - }); - }); - - describe('$editorIsInDraggingState', () => { - it("should return the editor's dragging state", () => { - expect(store.$editorIsInDraggingState()).toBe(false); - }); - - it("should return the editor's dragging state after a change", () => { - // This will trigger a change in the dragging state - store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); - - expect(store.$editorIsInDraggingState()).toBe(true); - }); - }); - - describe('$editorProps', () => { - it('should return the expected data on init', () => { - expect(store.$editorProps()).toEqual({ - showDialogs: true, - showEditorContent: true, - iframe: { - opacity: '0.5', - pointerEvents: 'auto', - src: 'http://localhost:3000/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', - wrapper: null - }, - progressBar: true, - contentletTools: null, - dropzone: null, - palette: { - variantId: DEFAULT_VARIANT_ID, - languageId: MOCK_RESPONSE_HEADLESS.viewAs.language.id, - containers: MOCK_RESPONSE_HEADLESS.containers - }, - seoResults: null - }); - }); - - it('should set iframe opacity to 1 when client is Ready', () => { - store.setIsClientReady(true); - - expect(store.$editorProps().iframe.opacity).toBe('1'); - }); - - describe('showDialogs', () => { - it('should have the value of false when we cannot edit the page', () => { - patchState(store, { canEditPage: false }); - - expect(store.$editorProps().showDialogs).toBe(false); - }); - - it('should have the value of false when we are not on edit state', () => { - patchState(store, { isEditState: false }); - - expect(store.$editorProps().showDialogs).toBe(false); - }); - }); - - describe('showEditorContent', () => { - it('should have showEditorContent as true when there is no socialMedia', () => { - expect(store.$editorProps().showEditorContent).toBe(true); - }); - }); - - describe('iframe', () => { - it('should have an opacity of 0.5 when loading', () => { - patchState(store, { status: UVE_STATUS.LOADING }); - - expect(store.$editorProps().iframe.opacity).toBe('0.5'); - }); - - it('should have pointerEvents as none when dragging', () => { - patchState(store, { state: EDITOR_STATE.DRAGGING }); - - expect(store.$editorProps().iframe.pointerEvents).toBe('none'); - }); - - it('should have pointerEvents as none when scroll-drag', () => { - patchState(store, { state: EDITOR_STATE.SCROLL_DRAG }); - - expect(store.$editorProps().iframe.pointerEvents).toBe('none'); - }); - - it('should have src as empty when the page is traditional', () => { - jest.spyOn(dotPageApiService, 'get').mockImplementation( - buildPageAPIResponseFromMock(MOCK_RESPONSE_VTL) - ); - - store.init(VTL_BASE_QUERY_PARAMS); - - expect(store.$editorProps().iframe.src).toBe(''); - }); - - it('should have a wrapper when a device is present', () => { - const device = mockDotDevices[0] as DotDeviceWithIcon; - - patchState(store, { device }); - - expect(store.$editorProps().iframe.wrapper).toEqual({ - width: device.cssWidth + BASE_IFRAME_MEASURE_UNIT, - height: device.cssHeight + BASE_IFRAME_MEASURE_UNIT - }); - }); - }); - - describe('progressBar', () => { - it('should have progressBar as true when the status is loading', () => { - patchState(store, { status: UVE_STATUS.LOADING }); - - expect(store.$editorProps().progressBar).toBe(true); - }); - - it('should have progressBar as true when the status is loaded but client is not ready', () => { - patchState(store, { status: UVE_STATUS.LOADED, isClientReady: false }); - - expect(store.$editorProps().progressBar).toBe(true); - }); - - it('should have progressBar as false when the status is loaded and client is ready', () => { - patchState(store, { status: UVE_STATUS.LOADED, isClientReady: true }); - - expect(store.$editorProps().progressBar).toBe(false); - }); - }); - - describe('contentletTools', () => { - it('should have contentletTools when contentletArea are present, can edit the page, is in edit state and not scrolling', () => { - patchState(store, { - isEditState: true, - canEditPage: true, - contentletArea: MOCK_CONTENTLET_AREA, - state: EDITOR_STATE.IDLE - }); - - expect(store.$editorProps().contentletTools).toEqual({ - isEnterprise: true, - contentletArea: MOCK_CONTENTLET_AREA, - hide: false - }); - }); - - it('should have hide as true when dragging', () => { - patchState(store, { - isEditState: true, - canEditPage: true, - contentletArea: MOCK_CONTENTLET_AREA, - state: EDITOR_STATE.DRAGGING - }); - - expect(store.$editorProps().contentletTools).toEqual({ - isEnterprise: true, - contentletArea: MOCK_CONTENTLET_AREA, - hide: true - }); - }); - - it('should be null when scrolling', () => { - patchState(store, { - isEditState: true, - canEditPage: true, - contentletArea: MOCK_CONTENTLET_AREA, - state: EDITOR_STATE.SCROLLING - }); - - expect(store.$editorProps().contentletTools).toEqual(null); - }); - - it("should not have contentletTools when the page can't be edited", () => { - patchState(store, { - isEditState: true, - canEditPage: false, - contentletArea: MOCK_CONTENTLET_AREA, - state: EDITOR_STATE.IDLE - }); - - expect(store.$editorProps().contentletTools).toBe(null); - }); - - it('should not have contentletTools when the contentletArea is not present', () => { - patchState(store, { - isEditState: true, - canEditPage: true, - state: EDITOR_STATE.IDLE - }); - - expect(store.$editorProps().contentletTools).toBe(null); - }); - - it('should not have contentletTools when the we are not in edit state', () => { - patchState(store, { - isEditState: false, - canEditPage: true, - contentletArea: MOCK_CONTENTLET_AREA, - state: EDITOR_STATE.IDLE - }); - - expect(store.$editorProps().contentletTools).toBe(null); - }); - }); - describe('dropzone', () => { - const bounds = getBoundsMock(ACTION_MOCK); - - it('should have dropzone when the state is dragging and the page can be edited', () => { - patchState(store, { - state: EDITOR_STATE.DRAGGING, - canEditPage: true, - dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, - bounds - }); - - expect(store.$editorProps().dropzone).toEqual({ - dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, - bounds - }); - }); - - it("should not have dropzone when the page can't be edited", () => { - patchState(store, { - state: EDITOR_STATE.DRAGGING, - canEditPage: false, - dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, - bounds - }); - - expect(store.$editorProps().dropzone).toBe(null); - }); - }); - - describe('palette', () => { - it('should be null if is not enterprise', () => { - patchState(store, { isEnterprise: false }); - - expect(store.$editorProps().palette).toBe(null); - }); - - it('should be null if canEditPage is false', () => { - patchState(store, { canEditPage: false }); - - expect(store.$editorProps().palette).toBe(null); - }); - - it('should be null if isEditState is false', () => { - patchState(store, { isEditState: false }); - - expect(store.$editorProps().palette).toBe(null); - }); - }); - - describe('seoResults', () => { - it('should have the expected data when ogTags and socialMedia is present', () => { - patchState(store, { - ogTags: seoOGTagsMock, - socialMedia: 'facebook' - }); - - expect(store.$editorProps().seoResults).toEqual({ - ogTags: seoOGTagsMock, - socialMedia: 'facebook' - }); - }); - - it('should be null when ogTags is not present', () => { - patchState(store, { - socialMedia: 'facebook' - }); - - expect(store.$editorProps().seoResults).toBe(null); - }); - - it('should be null when socialMedia is not present', () => { - patchState(store, { - ogTags: seoOGTagsMock - }); - - expect(store.$editorProps().seoResults).toBe(null); - }); - }); - }); - }); - - describe('withMethods', () => { - describe('updateEditorScrollState', () => { - it("should update the editor's scroll state and remove bounds when there is no drag item", () => { - store.updateEditorScrollState(); - - expect(store.state()).toEqual(EDITOR_STATE.SCROLLING); - expect(store.bounds()).toEqual([]); - }); - - it("should update the editor's scroll drag state and remove bounds when there is drag item", () => { - store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); - store.setEditorBounds(getBoundsMock(ACTION_MOCK)); - - store.updateEditorScrollState(); - - expect(store.state()).toEqual(EDITOR_STATE.SCROLL_DRAG); - expect(store.bounds()).toEqual([]); - }); - - it('should set the contentletArea to null when we are scrolling', () => { - store.setEditorState(EDITOR_STATE.SCROLLING); - - store.updateEditorScrollState(); - - expect(store.contentletArea()).toBe(null); - }); - }); - - describe('updateEditorOnScrollEnd', () => { - it("should update the editor's drag state when there is no drag item", () => { - store.updateEditorOnScrollEnd(); - - expect(store.state()).toEqual(EDITOR_STATE.IDLE); - }); - - it("should update the editor's drag state when there is drag item", () => { - store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); - - store.updateEditorOnScrollEnd(); - - expect(store.state()).toEqual(EDITOR_STATE.DRAGGING); - }); - }); - - describe('updateEditorScrollDragState', () => { - it('should update the store correctly', () => { - store.updateEditorScrollDragState(); - - expect(store.state()).toEqual(EDITOR_STATE.SCROLL_DRAG); - expect(store.bounds()).toEqual([]); - }); - }); - - describe('setEditorState', () => { - it('should update the state correctly', () => { - store.setEditorState(EDITOR_STATE.SCROLLING); - - expect(store.state()).toEqual(EDITOR_STATE.SCROLLING); - }); - }); - - describe('setEditorDragItem', () => { - it('should update the store correctly', () => { - store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); - - expect(store.dragItem()).toEqual(EMA_DRAG_ITEM_CONTENTLET_MOCK); - expect(store.state()).toEqual(EDITOR_STATE.DRAGGING); - }); - }); - - describe('setEditorContentletArea', () => { - it("should update the store's contentlet area", () => { - store.setEditorContentletArea(MOCK_CONTENTLET_AREA); - - expect(store.contentletArea()).toEqual(MOCK_CONTENTLET_AREA); - expect(store.state()).toEqual(EDITOR_STATE.IDLE); - }); - - it('should not update contentletArea if it is the same', () => { - store.setEditorContentletArea(MOCK_CONTENTLET_AREA); - - // We can have contentletArea and state at the same time we are inline editing - store.setEditorState(EDITOR_STATE.INLINE_EDITING); - - store.setEditorContentletArea(MOCK_CONTENTLET_AREA); - - expect(store.contentletArea()).toEqual(MOCK_CONTENTLET_AREA); - // State should not change - expect(store.state()).toEqual(EDITOR_STATE.INLINE_EDITING); - }); - }); - - describe('setEditorBounds', () => { - const bounds = getBoundsMock(ACTION_MOCK); - - it('should update the store correcly', () => { - store.setEditorBounds(bounds); - - expect(store.bounds()).toEqual(bounds); - }); - }); - - describe('resetEditorProperties', () => { - it('should reset the editor props corretcly', () => { - store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); - store.setEditorState(EDITOR_STATE.SCROLLING); - store.setEditorContentletArea(MOCK_CONTENTLET_AREA); - store.setEditorBounds(getBoundsMock(ACTION_MOCK)); - - store.resetEditorProperties(); - - expect(store.dragItem()).toBe(null); - expect(store.state()).toEqual(EDITOR_STATE.IDLE); - expect(store.contentletArea()).toBe(null); - expect(store.bounds()).toEqual([]); - }); - }); - describe('getPageSavePayload', () => { - it("should return the page's save payload", () => { - expect(store.getPageSavePayload(ACTION_PAYLOAD_MOCK)).toEqual({ - container: { - acceptTypes: 'test', - contentletsId: [], - identifier: 'container-identifier-123', - maxContentlets: 1, - uuid: 'uuid-123', - variantId: '123' - }, - contentlet: { - contentType: 'test', - identifier: 'contentlet-identifier-123', - inode: 'contentlet-inode-123', - onNumberOfPages: 1, - title: 'Hello World' - }, - language_id: '1', - pageContainers: [ - { - contentletsId: ['123', '456'], - identifier: '5363c6c6-5ba0-4946-b7af-cf875188ac2e', - uuid: '123' - }, - { - contentletsId: ['123'], - identifier: '5363c6c6-5ba0-4946-b7af-cf875188ac2e', - uuid: '456' - }, - { - contentletsId: ['123', '456'], - identifier: '/container/path', - uuid: '123' - }, - { - contentletsId: ['123'], - identifier: '/container/path', - uuid: '456' - } - ], - pageId: '123', - personaTag: 'dot:persona', - position: 'after' - }); - }); - }); - - describe('getCurrentTreeNode', () => { - it('should return the current TreeNode', () => { - const { container, contentlet } = ACTION_PAYLOAD_MOCK; - - expect(store.getCurrentTreeNode(container, contentlet)).toEqual({ - containerId: 'container-identifier-123', - contentId: 'contentlet-identifier-123', - pageId: '123', - personalization: 'dot:persona:dot:persona', - relationType: 'uuid-123', - treeOrder: '-1', - variantId: '123' - }); - }); - }); - - describe('setOgTags', () => { - it('should set the ogTags correctly', () => { - const ogTags = { - title: 'Title', - description: 'Description', - image: 'Image', - type: 'Type', - url: 'URL' - }; - - store.setOgTags(ogTags); - - expect(store.ogTags()).toEqual(ogTags); - }); - }); - }); - }); }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts new file mode 100644 index 000000000000..eb1047a03f3c --- /dev/null +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/withEditor.spec.ts @@ -0,0 +1,1077 @@ +import { describe, expect } from '@jest/globals'; +import { SpyObject } from '@ngneat/spectator'; +import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest'; +import { signalStore, withState, patchState } from '@ngrx/signals'; +import { of } from 'rxjs'; + +import { ActivatedRoute, Router } from '@angular/router'; + +import { CurrentUser } from '@dotcms/dotcms-js'; +import { DEFAULT_VARIANT_ID, DEFAULT_VARIANT_NAME, DotCMSContentlet } from '@dotcms/dotcms-models'; +import { getRunningExperimentMock, mockDotDevices, seoOGTagsMock } from '@dotcms/utils-testing'; + +import { withEditor } from './withEditor'; + +import { DotPageApiParams, DotPageApiService } from '../../../services/dot-page-api.service'; +import { BASE_IFRAME_MEASURE_UNIT, DEFAULT_PERSONA } from '../../../shared/consts'; +import { EDITOR_STATE, UVE_STATUS } from '../../../shared/enums'; +import { + ACTION_MOCK, + ACTION_PAYLOAD_MOCK, + EMA_DRAG_ITEM_CONTENTLET_MOCK, + getBoundsMock, + MOCK_CONTENTLET_AREA, + MOCK_RESPONSE_HEADLESS, + MOCK_RESPONSE_VTL +} from '../../../shared/mocks'; +import { DotDeviceWithIcon } from '../../../shared/models'; +import { getPersonalization, mapContainerStructureToArrayOfContainers } from '../../../utils'; +import { UVEState } from '../../models'; + +const mockCurrentUser: CurrentUser = { + email: 'admin@dotcms.com', + givenName: 'Admin', + loginAs: true, + roleId: 'e7d4e34e-5127-45fc-8123-d48b62d510e3', + surname: 'User', + userId: 'dotcms.org.1' +}; +const mockOtherUser: CurrentUser = { + email: 'admin2@dotcms.com', + givenName: 'Admin2', + loginAs: true, + roleId: '73ec980e-d74f-4cec-a4d0-e319061e20b9', + surname: 'User', + userId: 'dotcms.org.2808' +}; + +const emptyParams = {} as DotPageApiParams; + +const initialState: UVEState = { + isEnterprise: true, + languages: [], + pageAPIResponse: MOCK_RESPONSE_HEADLESS, + currentUser: null, + experiment: null, + errorCode: null, + params: { + ...emptyParams, + url: 'test-url', + language_id: '1', + 'com.dotmarketing.persona.id': 'dot:persona', + variantName: 'DEFAULT', + clientHost: 'http://localhost:3000' + }, + status: UVE_STATUS.LOADED, + isTraditionalPage: false, + canEditPage: true, + pageIsLocked: true +}; + +export const uveStoreMock = signalStore(withState(initialState), withEditor()); + +describe('withEditor', () => { + let spectator: SpectatorService>; + let dotPageApiService: SpyObject; + let store: InstanceType; + + const createService = createServiceFactory({ + service: uveStoreMock, + providers: [ + mockProvider(Router), + mockProvider(ActivatedRoute), + mockProvider(Router), + mockProvider(ActivatedRoute), + { + provide: DotPageApiService, + useValue: { + get() { + return of({}); + }, + getClientPage() { + return of({}); + }, + save: jest.fn() + } + } + ] + }); + + beforeEach(() => { + spectator = createService(); + store = spectator.service; + dotPageApiService = spectator.inject(DotPageApiService); + patchState(store, initialState); + }); + + describe('withEditorToolbar', () => { + describe('withComputed', () => { + describe('$toolbarProps', () => { + it('should return the base info', () => { + expect(store.$toolbarProps()).toEqual({ + apiUrl: '/api/v1/page/json/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', + bookmarksUrl: '/test-url?host_id=123-xyz-567-xxl&language_id=1', + copyUrl: + 'http://localhost:3000/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&host_id=123-xyz-567-xxl', + currentLanguage: MOCK_RESPONSE_HEADLESS.viewAs.language, + deviceSelector: { + apiLink: + 'http://localhost:3000/api/v1/page/json/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', + hideSocialMedia: true + }, + personaSelector: { + pageId: MOCK_RESPONSE_HEADLESS.page.identifier, + value: MOCK_RESPONSE_HEADLESS.viewAs.persona ?? DEFAULT_PERSONA + }, + runningExperiment: null, + showInfoDisplay: false, + unlockButton: null, + urlContentMap: null, + workflowActionsInode: MOCK_RESPONSE_HEADLESS.page.inode + }); + }); + + describe('urlContentMap', () => { + it('should return the urlContentMap if the state is edit', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + urlContentMap: { + title: 'Title', + inode: '123', + contentType: 'test' + } as unknown as DotCMSContentlet + } + }); + + expect(store.$toolbarProps().urlContentMap).toEqual({ + title: 'Title', + inode: '123', + contentType: 'test' + }); + }); + + it('should not return the urlContentMap if the state is not edit', () => { + patchState(store, { isEditState: false }); + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + urlContentMap: { + title: 'Title', + inode: '123', + contentType: 'test' + } as unknown as DotCMSContentlet + } + }); + + expect(store.$toolbarProps().urlContentMap).toEqual(null); + }); + }); + + describe('runningExperiment', () => { + it('should have a runningExperiment if the experiment is running', () => { + patchState(store, { experiment: getRunningExperimentMock() }); + + expect(store.$toolbarProps().runningExperiment).toEqual( + getRunningExperimentMock() + ); + }); + }); + + describe('workflowActionsInode', () => { + it("should not have an workflowActionsInode if the user can't edit the page", () => { + patchState(store, { canEditPage: false }); + + expect(store.$toolbarProps().workflowActionsInode).toBe(null); + }); + }); + + describe('unlockButton', () => { + it('should display unlockButton if the page is locked by another user and the current user can lock the page', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + lockedBy: mockOtherUser.userId, + canLock: true + } + }, + currentUser: mockCurrentUser, + status: UVE_STATUS.LOADED + }); + + expect(store.$toolbarProps().unlockButton).toEqual({ + inode: '123-i', + loading: false + }); + }); + + it('should not display unlockButton if the page is locked by the current user', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + lockedBy: mockCurrentUser.userId, + canLock: true + } + }, + currentUser: mockCurrentUser + }); + + expect(store.$toolbarProps().unlockButton).toBeNull(); + }); + + it('should not display unlockButton if the page is not locked', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: false, + canLock: true + } + }, + currentUser: mockCurrentUser + }); + + expect(store.$toolbarProps().unlockButton).toBeNull(); + }); + + it('should not display unlockButton if the user cannot lock the page', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + canLock: false + } + }, + currentUser: mockCurrentUser + }); + + expect(store.$toolbarProps().unlockButton).toBeNull(); + }); + }); + + describe('shouldShowInfoDisplay', () => { + it("should have shouldShowInfoDisplay as true if the user can't edit the page", () => { + patchState(store, { canEditPage: false }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(true); + }); + + it('should have shouldShowInfoDisplay as true if the device is set', () => { + patchState(store, { device: mockDotDevices[0] }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(true); + }); + + it('should have shouldShowInfoDisplay as true if the socialMedia is set', () => { + patchState(store, { socialMedia: 'facebook' }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(true); + }); + + it('should have shouldShowInfoDisplay as true if the page is a variant different from default', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + viewAs: { + ...MOCK_RESPONSE_HEADLESS.viewAs, + variantId: 'test' + } + } + }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(true); + }); + it('should have shouldShowInfoDisplay as true if the page is locked by another user', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + lockedBy: mockOtherUser.userId + } + }, + currentUser: mockCurrentUser + }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(true); + }); + + it('should have shouldShowInfoDisplay as false if the page is locked by the current user and other conditions are not met', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + lockedBy: mockCurrentUser.userId + } + }, + currentUser: mockCurrentUser, + canEditPage: true, + device: null, + socialMedia: null + }); + + expect(store.$toolbarProps().showInfoDisplay).toBe(false); + }); + }); + }); + + describe('$infoDisplayOptions', () => { + it('should be null in regular conditions', () => { + patchState(store, { canEditPage: true, pageAPIResponse: null }); + expect(store.$infoDisplayOptions()).toBe(null); + }); + + it('should return info for device', () => { + const device = mockDotDevices[0] as DotDeviceWithIcon; + + patchState(store, { device }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: device.icon, + info: { + message: 'iphone 200 x 100', + args: [] + }, + id: 'device', + actionIcon: 'pi pi-times' + }); + }); + + it('should return info for socialMedia', () => { + patchState(store, { socialMedia: 'Facebook' }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-facebook', + info: { + message: 'Viewing Facebook social media preview', + args: [] + }, + id: 'socialMedia', + actionIcon: 'pi pi-times' + }); + }); + + it('should return info when visiting a variant and can edit', () => { + const currentExperiment = getRunningExperimentMock(); + + const variantID = currentExperiment.trafficProportion.variants.find( + (variant) => variant.name !== DEFAULT_VARIANT_NAME + ).id; + + patchState(store, { + canEditPage: true, + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + viewAs: { + ...MOCK_RESPONSE_HEADLESS.viewAs, + variantId: variantID + } + }, + experiment: currentExperiment + }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-file-edit', + info: { + message: 'editpage.editing.variant', + args: ['Variant A'] + }, + id: 'variant', + actionIcon: 'pi pi-arrow-left' + }); + }); + + it('should return info when visiting a variant and can not edit', () => { + const currentExperiment = getRunningExperimentMock(); + + const variantID = currentExperiment.trafficProportion.variants.find( + (variant) => variant.name !== DEFAULT_VARIANT_NAME + ).id; + + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page + }, + viewAs: { + ...MOCK_RESPONSE_HEADLESS.viewAs, + variantId: variantID + } + }, + experiment: currentExperiment, + canEditPage: false + }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-file-edit', + info: { + message: 'editpage.viewing.variant', + args: ['Variant A'] + }, + id: 'variant', + actionIcon: 'pi pi-arrow-left' + }); + }); + + it('should return info when the page is locked and can lock', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + canLock: true, + lockedByName: 'John Doe' + } + } + }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-lock', + info: { + message: 'editpage.locked-by', + args: ['John Doe'] + }, + id: 'locked' + }); + }); + + it('should return info when the page is locked and cannot lock', () => { + patchState(store, { + pageAPIResponse: { + ...MOCK_RESPONSE_HEADLESS, + page: { + ...MOCK_RESPONSE_HEADLESS.page, + locked: true, + canLock: false, + lockedByName: 'John Doe' + } + } + }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-lock', + info: { + message: 'editpage.locked-contact-with', + args: ['John Doe'] + }, + id: 'locked' + }); + }); + + it('should return info when you cannot edit the page', () => { + patchState(store, { canEditPage: false }); + + expect(store.$infoDisplayOptions()).toEqual({ + icon: 'pi pi-exclamation-circle warning', + info: { message: 'editema.dont.have.edit.permission', args: [] }, + id: 'no-permission' + }); + }); + }); + }); + + describe('withMethods', () => { + it('should set the device with setDevice', () => { + const device = { + identifier: '123', + cssHeight: '120', + cssWidth: '120', + name: 'square', + inode: '1234', + icon: 'icon' + }; + + store.setDevice(device); + + expect(store.device()).toEqual(device); + expect(store.isEditState()).toBe(false); + }); + + it('should set the socialMedia with setSocialMedia', () => { + const socialMedia = 'facebook'; + + store.setSocialMedia(socialMedia); + + expect(store.socialMedia()).toEqual(socialMedia); + expect(store.isEditState()).toBe(false); + }); + + it('should reset the state with clearDeviceAndSocialMedia', () => { + store.clearDeviceAndSocialMedia(); + + expect(store.device()).toBe(null); + expect(store.socialMedia()).toBe(null); + expect(store.isEditState()).toBe(true); + }); + }); + }); + + describe('withSave', () => { + describe('withMethods', () => { + describe('savePage', () => { + it('should perform a save and patch the state', () => { + const saveSpy = jest + .spyOn(dotPageApiService, 'save') + .mockImplementation(() => of({})); + + // It's impossible to get a VTL when we are in Headless + // but I just want to check the state is being patched + const getClientPageSpy = jest + .spyOn(dotPageApiService, 'getClientPage') + .mockImplementation(() => of(MOCK_RESPONSE_VTL)); + + const payload = { + pageContainers: ACTION_PAYLOAD_MOCK.pageContainers, + pageId: MOCK_RESPONSE_HEADLESS.page.identifier, + params: store.params() + }; + + store.savePage(ACTION_PAYLOAD_MOCK.pageContainers); + + expect(saveSpy).toHaveBeenCalledWith(payload); + + expect(getClientPageSpy).toHaveBeenCalledWith( + store.params(), + store.clientRequestProps() + ); + + expect(store.status()).toBe(UVE_STATUS.LOADED); + expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_VTL); + }); + }); + }); + }); + + describe('withComputed', () => { + describe('$pageData', () => { + it('should return the expected data', () => { + expect(store.$pageData()).toEqual({ + containers: mapContainerStructureToArrayOfContainers( + MOCK_RESPONSE_HEADLESS.containers + ), + id: MOCK_RESPONSE_HEADLESS.page.identifier, + personalization: getPersonalization(MOCK_RESPONSE_HEADLESS.viewAs.persona), + languageId: MOCK_RESPONSE_HEADLESS.viewAs.language.id, + personaTag: MOCK_RESPONSE_HEADLESS.viewAs.persona.keyTag + }); + }); + }); + + describe('$reloadEditorContent', () => { + it('should return the expected data for Headless', () => { + patchState(store, { + pageAPIResponse: MOCK_RESPONSE_HEADLESS, + isTraditionalPage: false + }); + + expect(store.$reloadEditorContent()).toEqual({ + code: MOCK_RESPONSE_HEADLESS.page.rendered, + isTraditionalPage: false, + enableInlineEdit: true, + isClientReady: false + }); + }); + it('should return the expected data for VTL', () => { + patchState(store, { + pageAPIResponse: MOCK_RESPONSE_VTL, + isTraditionalPage: true, + isClientReady: true + }); + expect(store.$reloadEditorContent()).toEqual({ + code: MOCK_RESPONSE_VTL.page.rendered, + isTraditionalPage: true, + enableInlineEdit: true, + isClientReady: true + }); + }); + }); + + describe('$editorIsInDraggingState', () => { + it("should return the editor's dragging state", () => { + expect(store.$editorIsInDraggingState()).toBe(false); + }); + + it("should return the editor's dragging state after a change", () => { + // This will trigger a change in the dragging state + store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); + + expect(store.$editorIsInDraggingState()).toBe(true); + }); + }); + + describe('$editorProps', () => { + it('should return the expected data on init', () => { + expect(store.$editorProps()).toEqual({ + showDialogs: true, + showEditorContent: true, + iframe: { + opacity: '0.5', + pointerEvents: 'auto', + src: 'http://localhost:3000/test-url?language_id=1&com.dotmarketing.persona.id=dot%3Apersona&variantName=DEFAULT&clientHost=http%3A%2F%2Flocalhost%3A3000', + wrapper: null + }, + progressBar: true, + contentletTools: null, + dropzone: null, + palette: { + variantId: DEFAULT_VARIANT_ID, + languageId: MOCK_RESPONSE_HEADLESS.viewAs.language.id, + containers: MOCK_RESPONSE_HEADLESS.containers + }, + seoResults: null + }); + }); + + it('should set iframe opacity to 1 when client is Ready', () => { + store.setIsClientReady(true); + + expect(store.$editorProps().iframe.opacity).toBe('1'); + }); + + describe('showDialogs', () => { + it('should have the value of false when we cannot edit the page', () => { + patchState(store, { canEditPage: false }); + + expect(store.$editorProps().showDialogs).toBe(false); + }); + + it('should have the value of false when we are not on edit state', () => { + patchState(store, { isEditState: false }); + + expect(store.$editorProps().showDialogs).toBe(false); + }); + }); + + describe('showEditorContent', () => { + it('should have showEditorContent as true when there is no socialMedia', () => { + expect(store.$editorProps().showEditorContent).toBe(true); + }); + }); + + describe('iframe', () => { + it('should have an opacity of 0.5 when loading', () => { + patchState(store, { status: UVE_STATUS.LOADING }); + + expect(store.$editorProps().iframe.opacity).toBe('0.5'); + }); + + it('should have pointerEvents as none when dragging', () => { + patchState(store, { state: EDITOR_STATE.DRAGGING }); + + expect(store.$editorProps().iframe.pointerEvents).toBe('none'); + }); + + it('should have pointerEvents as none when scroll-drag', () => { + patchState(store, { state: EDITOR_STATE.SCROLL_DRAG }); + + expect(store.$editorProps().iframe.pointerEvents).toBe('none'); + }); + + it('should have src as empty when the page is traditional', () => { + patchState(store, { + pageAPIResponse: MOCK_RESPONSE_VTL, + isTraditionalPage: true + }); + + expect(store.$editorProps().iframe.src).toBe(''); + }); + + it('should have a wrapper when a device is present', () => { + const device = mockDotDevices[0] as DotDeviceWithIcon; + + patchState(store, { device }); + + expect(store.$editorProps().iframe.wrapper).toEqual({ + width: device.cssWidth + BASE_IFRAME_MEASURE_UNIT, + height: device.cssHeight + BASE_IFRAME_MEASURE_UNIT + }); + }); + }); + + describe('progressBar', () => { + it('should have progressBar as true when the status is loading', () => { + patchState(store, { status: UVE_STATUS.LOADING }); + + expect(store.$editorProps().progressBar).toBe(true); + }); + + it('should have progressBar as true when the status is loaded but client is not ready', () => { + patchState(store, { status: UVE_STATUS.LOADED, isClientReady: false }); + + expect(store.$editorProps().progressBar).toBe(true); + }); + + it('should have progressBar as false when the status is loaded and client is ready', () => { + patchState(store, { status: UVE_STATUS.LOADED, isClientReady: true }); + + expect(store.$editorProps().progressBar).toBe(false); + }); + }); + + describe('contentletTools', () => { + it('should have contentletTools when contentletArea are present, can edit the page, is in edit state and not scrolling', () => { + patchState(store, { + isEditState: true, + canEditPage: true, + contentletArea: MOCK_CONTENTLET_AREA, + state: EDITOR_STATE.IDLE + }); + + expect(store.$editorProps().contentletTools).toEqual({ + isEnterprise: true, + contentletArea: MOCK_CONTENTLET_AREA, + hide: false + }); + }); + + it('should have hide as true when dragging', () => { + patchState(store, { + isEditState: true, + canEditPage: true, + contentletArea: MOCK_CONTENTLET_AREA, + state: EDITOR_STATE.DRAGGING + }); + + expect(store.$editorProps().contentletTools).toEqual({ + isEnterprise: true, + contentletArea: MOCK_CONTENTLET_AREA, + hide: true + }); + }); + + it('should be null when scrolling', () => { + patchState(store, { + isEditState: true, + canEditPage: true, + contentletArea: MOCK_CONTENTLET_AREA, + state: EDITOR_STATE.SCROLLING + }); + + expect(store.$editorProps().contentletTools).toEqual(null); + }); + + it("should not have contentletTools when the page can't be edited", () => { + patchState(store, { + isEditState: true, + canEditPage: false, + contentletArea: MOCK_CONTENTLET_AREA, + state: EDITOR_STATE.IDLE + }); + + expect(store.$editorProps().contentletTools).toBe(null); + }); + + it('should not have contentletTools when the contentletArea is not present', () => { + patchState(store, { + isEditState: true, + canEditPage: true, + state: EDITOR_STATE.IDLE + }); + + expect(store.$editorProps().contentletTools).toBe(null); + }); + + it('should not have contentletTools when the we are not in edit state', () => { + patchState(store, { + isEditState: false, + canEditPage: true, + contentletArea: MOCK_CONTENTLET_AREA, + state: EDITOR_STATE.IDLE + }); + + expect(store.$editorProps().contentletTools).toBe(null); + }); + }); + describe('dropzone', () => { + const bounds = getBoundsMock(ACTION_MOCK); + + it('should have dropzone when the state is dragging and the page can be edited', () => { + patchState(store, { + state: EDITOR_STATE.DRAGGING, + canEditPage: true, + dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, + bounds + }); + + expect(store.$editorProps().dropzone).toEqual({ + dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, + bounds + }); + }); + + it("should not have dropzone when the page can't be edited", () => { + patchState(store, { + state: EDITOR_STATE.DRAGGING, + canEditPage: false, + dragItem: EMA_DRAG_ITEM_CONTENTLET_MOCK, + bounds + }); + + expect(store.$editorProps().dropzone).toBe(null); + }); + }); + + describe('palette', () => { + it('should be null if is not enterprise', () => { + patchState(store, { isEnterprise: false }); + + expect(store.$editorProps().palette).toBe(null); + }); + + it('should be null if canEditPage is false', () => { + patchState(store, { canEditPage: false }); + + expect(store.$editorProps().palette).toBe(null); + }); + + it('should be null if isEditState is false', () => { + patchState(store, { isEditState: false }); + + expect(store.$editorProps().palette).toBe(null); + }); + }); + + describe('seoResults', () => { + it('should have the expected data when ogTags and socialMedia is present', () => { + patchState(store, { + ogTags: seoOGTagsMock, + socialMedia: 'facebook' + }); + + expect(store.$editorProps().seoResults).toEqual({ + ogTags: seoOGTagsMock, + socialMedia: 'facebook' + }); + }); + + it('should be null when ogTags is not present', () => { + patchState(store, { + socialMedia: 'facebook' + }); + + expect(store.$editorProps().seoResults).toBe(null); + }); + + it('should be null when socialMedia is not present', () => { + patchState(store, { + ogTags: seoOGTagsMock + }); + + expect(store.$editorProps().seoResults).toBe(null); + }); + }); + }); + }); + + describe('withMethods', () => { + describe('updateEditorScrollState', () => { + it("should update the editor's scroll state and remove bounds when there is no drag item", () => { + store.updateEditorScrollState(); + + expect(store.state()).toEqual(EDITOR_STATE.SCROLLING); + expect(store.bounds()).toEqual([]); + }); + + it("should update the editor's scroll drag state and remove bounds when there is drag item", () => { + store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); + store.setEditorBounds(getBoundsMock(ACTION_MOCK)); + + store.updateEditorScrollState(); + + expect(store.state()).toEqual(EDITOR_STATE.SCROLL_DRAG); + expect(store.bounds()).toEqual([]); + }); + + it('should set the contentletArea to null when we are scrolling', () => { + store.setEditorState(EDITOR_STATE.SCROLLING); + + store.updateEditorScrollState(); + + expect(store.contentletArea()).toBe(null); + }); + }); + + describe('updateEditorOnScrollEnd', () => { + it("should update the editor's drag state when there is no drag item", () => { + store.updateEditorOnScrollEnd(); + + expect(store.state()).toEqual(EDITOR_STATE.IDLE); + }); + + it("should update the editor's drag state when there is drag item", () => { + store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); + + store.updateEditorOnScrollEnd(); + + expect(store.state()).toEqual(EDITOR_STATE.DRAGGING); + }); + }); + + describe('updateEditorScrollDragState', () => { + it('should update the store correctly', () => { + store.updateEditorScrollDragState(); + + expect(store.state()).toEqual(EDITOR_STATE.SCROLL_DRAG); + expect(store.bounds()).toEqual([]); + }); + }); + + describe('setEditorState', () => { + it('should update the state correctly', () => { + store.setEditorState(EDITOR_STATE.SCROLLING); + + expect(store.state()).toEqual(EDITOR_STATE.SCROLLING); + }); + }); + + describe('setEditorDragItem', () => { + it('should update the store correctly', () => { + store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); + + expect(store.dragItem()).toEqual(EMA_DRAG_ITEM_CONTENTLET_MOCK); + expect(store.state()).toEqual(EDITOR_STATE.DRAGGING); + }); + }); + + describe('setEditorContentletArea', () => { + it("should update the store's contentlet area", () => { + store.setEditorContentletArea(MOCK_CONTENTLET_AREA); + + expect(store.contentletArea()).toEqual(MOCK_CONTENTLET_AREA); + expect(store.state()).toEqual(EDITOR_STATE.IDLE); + }); + + it('should not update contentletArea if it is the same', () => { + store.setEditorContentletArea(MOCK_CONTENTLET_AREA); + + // We can have contentletArea and state at the same time we are inline editing + store.setEditorState(EDITOR_STATE.INLINE_EDITING); + + store.setEditorContentletArea(MOCK_CONTENTLET_AREA); + + expect(store.contentletArea()).toEqual(MOCK_CONTENTLET_AREA); + // State should not change + expect(store.state()).toEqual(EDITOR_STATE.INLINE_EDITING); + }); + }); + + describe('setEditorBounds', () => { + const bounds = getBoundsMock(ACTION_MOCK); + + it('should update the store correcly', () => { + store.setEditorBounds(bounds); + + expect(store.bounds()).toEqual(bounds); + }); + }); + + describe('resetEditorProperties', () => { + it('should reset the editor props corretcly', () => { + store.setEditorDragItem(EMA_DRAG_ITEM_CONTENTLET_MOCK); + store.setEditorState(EDITOR_STATE.SCROLLING); + store.setEditorContentletArea(MOCK_CONTENTLET_AREA); + store.setEditorBounds(getBoundsMock(ACTION_MOCK)); + + store.resetEditorProperties(); + + expect(store.dragItem()).toBe(null); + expect(store.state()).toEqual(EDITOR_STATE.IDLE); + expect(store.contentletArea()).toBe(null); + expect(store.bounds()).toEqual([]); + }); + }); + describe('getPageSavePayload', () => { + it("should return the page's save payload", () => { + expect(store.getPageSavePayload(ACTION_PAYLOAD_MOCK)).toEqual({ + container: { + acceptTypes: 'test', + contentletsId: [], + identifier: 'container-identifier-123', + maxContentlets: 1, + uuid: 'uuid-123', + variantId: '123' + }, + contentlet: { + contentType: 'test', + identifier: 'contentlet-identifier-123', + inode: 'contentlet-inode-123', + onNumberOfPages: 1, + title: 'Hello World' + }, + language_id: '1', + pageContainers: [ + { + contentletsId: ['123', '456'], + identifier: '5363c6c6-5ba0-4946-b7af-cf875188ac2e', + uuid: '123' + }, + { + contentletsId: ['123'], + identifier: '5363c6c6-5ba0-4946-b7af-cf875188ac2e', + uuid: '456' + }, + { + contentletsId: ['123', '456'], + identifier: '/container/path', + uuid: '123' + }, + { + contentletsId: ['123'], + identifier: '/container/path', + uuid: '456' + } + ], + pageId: '123', + personaTag: 'dot:persona', + position: 'after' + }); + }); + }); + + describe('getCurrentTreeNode', () => { + it('should return the current TreeNode', () => { + const { container, contentlet } = ACTION_PAYLOAD_MOCK; + + expect(store.getCurrentTreeNode(container, contentlet)).toEqual({ + containerId: 'container-identifier-123', + contentId: 'contentlet-identifier-123', + pageId: '123', + personalization: 'dot:persona:dot:persona', + relationType: 'uuid-123', + treeOrder: '-1', + variantId: '123' + }); + }); + }); + + describe('setOgTags', () => { + it('should set the ogTags correctly', () => { + const ogTags = { + title: 'Title', + description: 'Description', + image: 'Image', + type: 'Type', + url: 'URL' + }; + + store.setOgTags(ogTags); + + expect(store.ogTags()).toEqual(ogTags); + }); + }); + }); +}); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts new file mode 100644 index 000000000000..5a87bf8c2882 --- /dev/null +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/layout/wihtLayout.spec.ts @@ -0,0 +1,77 @@ +import { describe, expect } from '@jest/globals'; +import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest'; +import { signalStore, withState } from '@ngrx/signals'; + +import { ActivatedRoute, Router } from '@angular/router'; + +import { withLayout } from './withLayout'; + +import { DotPageApiParams } from '../../../services/dot-page-api.service'; +import { UVE_STATUS } from '../../../shared/enums'; +import { MOCK_RESPONSE_HEADLESS } from '../../../shared/mocks'; +import { mapContainerStructureToDotContainerMap } from '../../../utils'; +import { UVEState } from '../../models'; + +const emptyParams = {} as DotPageApiParams; + +const initialState: UVEState = { + isEnterprise: false, + languages: [], + pageAPIResponse: MOCK_RESPONSE_HEADLESS, + currentUser: null, + experiment: null, + errorCode: null, + params: emptyParams, + status: UVE_STATUS.LOADING, + isTraditionalPage: true, + canEditPage: false, + pageIsLocked: true +}; + +export const uveStoreMock = signalStore(withState(initialState), withLayout()); + +describe('withLayout', () => { + let spectator: SpectatorService>; + let store: InstanceType; + const createService = createServiceFactory({ + service: uveStoreMock, + providers: [mockProvider(Router), mockProvider(ActivatedRoute)] + }); + + beforeEach(() => { + spectator = createService(); + store = spectator.service; + }); + + describe('withComputed', () => { + describe('$layoutProps', () => { + it('should return the layout props', () => { + expect(store.$layoutProps()).toEqual({ + containersMap: mapContainerStructureToDotContainerMap( + MOCK_RESPONSE_HEADLESS.containers + ), + layout: MOCK_RESPONSE_HEADLESS.layout, + template: { + identifier: MOCK_RESPONSE_HEADLESS.template.identifier, + themeId: MOCK_RESPONSE_HEADLESS.template.theme, + anonymous: false + }, + pageId: MOCK_RESPONSE_HEADLESS.page.identifier + }); + }); + }); + }); + + describe('withMethods', () => { + it('should update the layout', () => { + const layout = { + ...MOCK_RESPONSE_HEADLESS.layout, + title: 'New layout' + }; + + store.updateLayout(layout); + + expect(store.pageAPIResponse().layout).toEqual(layout); + }); + }); +}); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts new file mode 100644 index 000000000000..d753c4ffd7fe --- /dev/null +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.spec.ts @@ -0,0 +1,354 @@ +import { describe, expect } from '@jest/globals'; +import { + createServiceFactory, + mockProvider, + SpectatorService, + SpyObject +} from '@ngneat/spectator/jest'; +import { signalStore, withState } from '@ngrx/signals'; +import { of } from 'rxjs'; + +import { ActivatedRoute, ActivatedRouteSnapshot, ParamMap, Router } from '@angular/router'; + +import { + DotExperimentsService, + DotLanguagesService, + DotLicenseService, + DotMessageService +} from '@dotcms/data-access'; +import { LoginService } from '@dotcms/dotcms-js'; +import { + CurrentUserDataMock, + DotLanguagesServiceMock, + getDraftExperimentMock, + getRunningExperimentMock, + getScheduleExperimentMock, + MockDotMessageService, + mockLanguageArray +} from '@dotcms/utils-testing'; + +import { withLoad } from './withLoad'; + +import { + DotPageApiParams, + DotPageApiResponse, + DotPageApiService +} from '../../../services/dot-page-api.service'; +import { UVE_STATUS } from '../../../shared/enums'; +import { + getVanityUrl, + HEADLESS_BASE_QUERY_PARAMS, + MOCK_RESPONSE_HEADLESS, + MOCK_RESPONSE_VTL, + PERMANENT_REDIRECT_VANITY_URL, + TEMPORARY_REDIRECT_VANITY_URL, + VTL_BASE_QUERY_PARAMS +} from '../../../shared/mocks'; +import { UVEState } from '../../models'; + +const buildPageAPIResponseFromMock = + (mock) => + ({ url }) => + of({ + ...mock, + page: { + ...mock.page, + pageURI: url + } + }); +const emptyParams = {} as DotPageApiParams; + +const initialState: UVEState = { + isEnterprise: false, + languages: [], + pageAPIResponse: null, + currentUser: null, + experiment: null, + errorCode: null, + params: emptyParams, + status: UVE_STATUS.LOADING, + isTraditionalPage: true, + canEditPage: false, + pageIsLocked: true +}; + +export const uveStoreMock = signalStore(withState(initialState), withLoad()); + +describe('withLoad', () => { + let spectator: SpectatorService>; + let store: InstanceType; + let dotPageApiService: SpyObject; + let activatedRoute: SpyObject; + let router: SpyObject; + + const createService = createServiceFactory({ + service: uveStoreMock, + providers: [ + mockProvider(Router), + mockProvider(ActivatedRoute), + { + provide: DotPageApiService, + useValue: { + get() { + return of({}); + }, + getClientPage() { + return of({}); + }, + save: jest.fn() + } + }, + { + provide: DotLicenseService, + useValue: { + isEnterprise: () => of(true) + } + }, + { + provide: DotMessageService, + useValue: new MockDotMessageService({}) + }, + { + provide: LoginService, + useValue: { + getCurrentUser: () => of(CurrentUserDataMock) + } + }, + { + provide: DotLanguagesService, + useValue: new DotLanguagesServiceMock() + }, + + { + provide: DotExperimentsService, + useValue: { + getById(experimentId: string) { + if (experimentId == 'i-have-a-running-experiment') { + return of(getRunningExperimentMock()); + } else if (experimentId == 'i-have-a-scheduled-experiment') { + return of(getScheduleExperimentMock()); + } else if (experimentId) return of(getDraftExperimentMock()); + + return of(undefined); + } + } + } + ] + }); + + beforeEach(() => { + spectator = createService(); + store = spectator.service; + + dotPageApiService = spectator.inject(DotPageApiService); + router = spectator.inject(Router); + activatedRoute = spectator.inject(ActivatedRoute); + jest.spyOn(dotPageApiService, 'get').mockImplementation( + buildPageAPIResponseFromMock(MOCK_RESPONSE_HEADLESS) + ); + + store.init(HEADLESS_BASE_QUERY_PARAMS); + }); + + describe('withMethods', () => { + it('should load the store with the base data', () => { + expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_HEADLESS); + expect(store.isEnterprise()).toBe(true); + expect(store.currentUser()).toEqual(CurrentUserDataMock); + expect(store.experiment()).toBe(undefined); + expect(store.languages()).toBe(mockLanguageArray); + expect(store.params()).toEqual(HEADLESS_BASE_QUERY_PARAMS); + expect(store.canEditPage()).toBe(true); + expect(store.pageIsLocked()).toBe(false); + expect(store.status()).toBe(UVE_STATUS.LOADED); + expect(store.isTraditionalPage()).toBe(false); + expect(store.isClientReady()).toBe(false); + }); + + it('should load the store with the base data for traditional page', () => { + jest.spyOn(dotPageApiService, 'get').mockImplementation( + buildPageAPIResponseFromMock(MOCK_RESPONSE_VTL) + ); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(store.pageAPIResponse()).toEqual(MOCK_RESPONSE_VTL); + expect(store.isEnterprise()).toBe(true); + expect(store.currentUser()).toEqual(CurrentUserDataMock); + expect(store.experiment()).toBe(undefined); + expect(store.languages()).toBe(mockLanguageArray); + expect(store.params()).toEqual(VTL_BASE_QUERY_PARAMS); + expect(store.canEditPage()).toBe(true); + expect(store.pageIsLocked()).toBe(false); + expect(store.status()).toBe(UVE_STATUS.LOADED); + expect(store.isTraditionalPage()).toBe(true); + expect(store.isClientReady()).toBe(true); + }); + + it('should navigate when the page is a vanityUrl permanent redirect', () => { + const permanentRedirect = getVanityUrl( + VTL_BASE_QUERY_PARAMS.url, + PERMANENT_REDIRECT_VANITY_URL + ) as unknown as DotPageApiResponse; + + const forwardTo = PERMANENT_REDIRECT_VANITY_URL.forwardTo; + + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => of(permanentRedirect)); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).toHaveBeenCalledWith([], { + queryParams: { + ...VTL_BASE_QUERY_PARAMS, + url: forwardTo + }, + queryParamsHandling: 'merge' + }); + }); + + it('should navigate when the page is a vanityUrl temporary redirect', () => { + const temporaryRedirect = getVanityUrl( + VTL_BASE_QUERY_PARAMS.url, + TEMPORARY_REDIRECT_VANITY_URL + ) as unknown as DotPageApiResponse; + + const forwardTo = TEMPORARY_REDIRECT_VANITY_URL.forwardTo; + + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => of(temporaryRedirect)); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).toHaveBeenCalledWith([], { + queryParams: { + ...VTL_BASE_QUERY_PARAMS, + url: forwardTo + }, + queryParamsHandling: 'merge' + }); + }); + + it('should navigate to content when the layout is disable by page.canEdit and current route is layout', () => { + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => + of({ + ...MOCK_RESPONSE_VTL, + page: { + ...MOCK_RESPONSE_VTL.page, + canEdit: false + } + }) + ); + + jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ + snapshot: { + url: [ + { + path: 'layout', + parameters: {}, + parameterMap: {} as unknown as ParamMap + } + ] + } as unknown as ActivatedRouteSnapshot + } as unknown as ActivatedRoute); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).toHaveBeenCalledWith(['edit-page/content'], { + queryParamsHandling: 'merge' + }); + }); + + it('should navigate to content when the layout is disable by template.drawed and current route is layout', () => { + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => + of({ + ...MOCK_RESPONSE_VTL, + template: { + ...MOCK_RESPONSE_VTL.template, + drawed: false + } + }) + ); + + jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ + snapshot: { + url: [ + { + path: 'layout', + parameters: {}, + parameterMap: {} as unknown as ParamMap + } + ] + } as unknown as ActivatedRouteSnapshot + } as unknown as ActivatedRoute); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).toHaveBeenCalledWith(['edit-page/content'], { + queryParamsHandling: 'merge' + }); + }); + + it('should not navigate to content when the layout is disable by template.drawed and current route is not layout', () => { + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => + of({ + ...MOCK_RESPONSE_VTL, + template: { + ...MOCK_RESPONSE_VTL.template, + drawed: false + } + }) + ); + + jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ + snapshot: { + url: [ + { + path: 'rules', + parameters: {}, + parameterMap: {} as unknown as ParamMap + } + ] + } as unknown as ActivatedRouteSnapshot + } as unknown as ActivatedRoute); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).not.toHaveBeenCalled(); + }); + + it('should not navigate to content when the layout is disable by page.canEdit and current route is not layout', () => { + jest.spyOn(dotPageApiService, 'get').mockImplementation(() => + of({ + ...MOCK_RESPONSE_VTL, + page: { + ...MOCK_RESPONSE_VTL.page, + canEdit: false + } + }) + ); + + jest.spyOn(activatedRoute, 'firstChild', 'get').mockReturnValue({ + snapshot: { + url: [ + { + path: 'rules', + parameters: {}, + parameterMap: {} as unknown as ParamMap + } + ] + } as unknown as ActivatedRouteSnapshot + } as unknown as ActivatedRoute); + + store.init(VTL_BASE_QUERY_PARAMS); + + expect(router.navigate).not.toHaveBeenCalled(); + }); + + it('should reload the store with the same queryParams', () => { + const getPageSpy = jest.spyOn(dotPageApiService, 'get'); + + store.reload(); + + expect(getPageSpy).toHaveBeenCalledWith(store.params()); + }); + }); +}); diff --git a/examples/angular/src/app/pages/pages.component.ts b/examples/angular/src/app/pages/pages.component.ts index b35d30b517f9..45fbf51a3dfb 100644 --- a/examples/angular/src/app/pages/pages.component.ts +++ b/examples/angular/src/app/pages/pages.component.ts @@ -1,10 +1,4 @@ -import { - Component, - DestroyRef, - OnInit, - inject, - signal, -} from '@angular/core'; +import { Component, DestroyRef, OnInit, inject, signal } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; import { NavigationEnd } from '@angular/router'; @@ -38,7 +32,6 @@ type PageRender = { status: 'idle' | 'success' | 'error' | 'loading'; }; - @Component({ selector: 'app-dotcms-page', standalone: true, @@ -72,40 +65,41 @@ export class DotCMSPagesComponent implements OnInit { ngOnInit() { this.#router.events .pipe( - filter((event): event is NavigationEnd => event instanceof NavigationEnd), + filter( + (event): event is NavigationEnd => event instanceof NavigationEnd + ), startWith(null), // Trigger initial load tap(() => this.#setLoading()), switchMap(() => this.#pageService.getPageAndNavigation(this.#route, this.editorCofig)), takeUntilDestroyed(this.#destroyRef) ) - .subscribe( - ({ page, nav }: { - page: DotCMSPageAsset | { error: PageError }; - nav: DotcmsNavigationItem | null; - }) => { - if ('error' in page) { - this.#setError(page.error); - } else { - const { vanityUrl } = page; + .subscribe(({ page = {}, nav, error }) => { + if (error) { + this.#setError(error); + return; + } - if (vanityUrl?.permanentRedirect || vanityUrl?.temporaryRedirect) { - this.#router.navigate([vanityUrl.forwardTo]); - return; - } + const { vanityUrl } = page || {}; - this.#setPageContent(page, nav); - } + if (vanityUrl?.permanentRedirect || vanityUrl?.temporaryRedirect) { + this.#router.navigate([vanityUrl.forwardTo]); + return; } - ); + + this.#setPageContent(page as DotCMSPageAsset, nav); + }); } - #setPageContent(page: DotCMSPageAsset, nav: DotcmsNavigationItem | null) { - this.$context.update((state) => ({ + #setPageContent( + page: DotCMSPageAsset, + nav: DotcmsNavigationItem | null + ) { + this.$context.set({ status: 'success', page, nav, error: null, - })); + }); } #setLoading() { diff --git a/examples/angular/src/app/pages/services/page.service.ts b/examples/angular/src/app/pages/services/page.service.ts index fbf5e724bb04..6efbd088e1aa 100644 --- a/examples/angular/src/app/pages/services/page.service.ts +++ b/examples/angular/src/app/pages/services/page.service.ts @@ -1,14 +1,23 @@ import { inject, Injectable } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { from, Observable, shareReplay } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; +import { forkJoin, from, Observable, of, shareReplay } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; -import { getPageRequestParams } from '@dotcms/client'; +import { getPageRequestParams, isInsideEditor } from '@dotcms/client'; import { DotcmsNavigationItem, DotCMSPageAsset } from '@dotcms/angular'; import { PageError } from '../pages.component'; import { DOTCMS_CLIENT_TOKEN } from '../../app.config'; +export interface PageResponse { + page: DotCMSPageAsset | null; + error?: PageError; +} + +export interface PageAndNavResponse extends PageResponse { + nav: DotcmsNavigationItem | null; +} + @Injectable({ providedIn: 'root', }) @@ -27,20 +36,20 @@ export class PageService { getPageAndNavigation( route: ActivatedRoute, config: any - ): Observable<{ - page: DotCMSPageAsset | { error: PageError }; - nav: DotcmsNavigationItem | null; - }> { + ): Observable { if (!this.navObservable) { this.navObservable = this.fetchNavigation(route); } - return this.fetchPage(route, config).pipe( - switchMap((page) => - this.navObservable.pipe( - map((nav) => ({ page, nav })) - ) - ) + return forkJoin({ + nav: this.navObservable, + pageAsset: this.fetchPage(route, config), + }).pipe( + map(({ nav, pageAsset }) => { + const { page, error } = pageAsset; + + return { nav, page, error }; + }) ); } @@ -65,7 +74,7 @@ export class PageService { private fetchPage( route: ActivatedRoute, config: any - ): Observable { + ): Observable { const queryParams = route.snapshot.queryParamMap; const url = route.snapshot.url.map((segment) => segment.path).join('/'); const path = url || '/'; @@ -75,24 +84,30 @@ export class PageService { params: queryParams, }); - return from( - this.client.page - .get({ ...pageParams, ...config.params }) - .then((response) => { - if (!(response as any).layout) { - return { error: { message: 'You might be using an advanced template, or your dotCMS instance might lack an enterprise license.', status: 'Page without layout' } }; - } - - return response as DotCMSPageAsset - }) - .catch((e) => { - console.error(`Error fetching page: ${e.message}`); - const error: PageError = { - message: e.message, - status: e.status, + return from(this.client.page.get({ ...pageParams, ...config.params })).pipe( + map((page: any) => { + if (!page?.layout) { + return { + page: null, + error: { + message: + 'You might be using an advanced template, or your dotCMS instance might lack an enterprise license.', + status: 'Page without layout', + }, }; - return { error }; - }) + } + + return { page, error: null }; + }), + catchError((error) => { + // If the page is not found and we are inside the editor, return an empty object + // The editor will get the working/unpublished page + if (error.status === 404 && isInsideEditor()) { + return of({ page: {}, error: null } as any); + } + + return of({ page: null, error }); + }) ); } } diff --git a/examples/astro/src/components/Error.astro b/examples/astro/src/components/Error.astro index 67a228aae495..e47dd7bff5c0 100644 --- a/examples/astro/src/components/Error.astro +++ b/examples/astro/src/components/Error.astro @@ -1,7 +1,5 @@ --- const { error } = Astro.props; - -const currentQueryParams = Astro.url.search; --- { @@ -10,32 +8,10 @@ const currentQueryParams = Astro.url.search;
- {error.status === 404 ? ( - <> -

- 404 -

-

- Something's missing. -

-

- Sorry, we can't find that page. You'll find lots to - explore on the home page. -

- -
- Return Home -
-
- - ) : ( - <> -

- {error.status} -

-

{error.message}

- - )} +

+ {error.status} +

+

{error.message}

diff --git a/examples/astro/src/react/components/notFound.tsx b/examples/astro/src/react/components/notFound.tsx new file mode 100644 index 000000000000..70663f34ddff --- /dev/null +++ b/examples/astro/src/react/components/notFound.tsx @@ -0,0 +1,27 @@ +export default function NotFound() { + return ( +
+
+
+
+

+ 404 +

+

+ Something's missing. +

+

+ Sorry, we can't find that page. You'll find lots to + explore on the home page. +

+ +
+ Return Home +
+
+
+
+
+
+ ); +} diff --git a/examples/astro/src/react/hooks/usePageAsset.ts b/examples/astro/src/react/hooks/usePageAsset.ts index 8e37c1d49d56..d0cd3242a32a 100644 --- a/examples/astro/src/react/hooks/usePageAsset.ts +++ b/examples/astro/src/react/hooks/usePageAsset.ts @@ -1,11 +1,20 @@ +import { useEffect, useState } from "react"; +import { + CUSTOMER_ACTIONS, + isInsideEditor, + postMessageToEditor, +} from "@dotcms/client"; import type { DotCMSPageAsset } from "@dotcms/types"; import { client } from "@utils/client"; -import { useEffect, useState } from "react"; export const usePageAsset = (currentPageAsset: DotCMSPageAsset | undefined) => { const [pageAsset, setPageAsset] = useState(); useEffect(() => { + if (!isInsideEditor()) { + return; + } + client.editor.on("changes", (page) => { if (!page) { return; @@ -13,6 +22,13 @@ export const usePageAsset = (currentPageAsset: DotCMSPageAsset | undefined) => { setPageAsset(page as DotCMSPageAsset); }); + // If the page is not found, let the editor know + if (!currentPageAsset) { + postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY }); + + return; + } + return () => { client.editor.off("changes"); }; diff --git a/examples/astro/src/react/myPage.tsx b/examples/astro/src/react/myPage.tsx index 0c15be0d3ee6..252cf9f8850b 100644 --- a/examples/astro/src/react/myPage.tsx +++ b/examples/astro/src/react/myPage.tsx @@ -8,6 +8,8 @@ import type { FC } from "react"; import { Navigation } from "./layout/navigation"; import { Footer } from "./layout/footer/footer"; +import NotFound from "./components/notFound"; + import type { DotcmsNavigationItem, DotCMSPageAsset } from "@dotcms/types"; export type MyPageProps = { @@ -18,6 +20,10 @@ export type MyPageProps = { export const MyPage: FC = ({ pageAsset, nav }) => { pageAsset = usePageAsset(pageAsset); + if(!pageAsset) { + return + } + return (
{pageAsset?.layout.header && ( diff --git a/examples/astro/src/utils/client.ts b/examples/astro/src/utils/client.ts index e5dae4b6475c..5d0f3c87d06d 100644 --- a/examples/astro/src/utils/client.ts +++ b/examples/astro/src/utils/client.ts @@ -20,28 +20,50 @@ export type GetPageDataResponse = { export const getPageData = async ( slug: string | undefined, params: URLSearchParams, -): Promise => { - try { - const path = slug || "/"; +) => { + const path = slug || "/"; + const pageParams = getPageRequestParams({ + path, + params, + }); + + const { pageAsset, error: pageError } = await fetchPageData(pageParams); + const { nav, error: navError } = await fetchNavData(pageParams.language_id); - const pageRequestParams = getPageRequestParams({ - path, - params, - }); + return { + nav, + pageAsset, + error: pageError || navError, + }; +}; +const fetchPageData = async (params: any) => { + try { const pageAsset = (await client.page.get({ - ...pageRequestParams, + ...params, depth: 3, })) as DotCMSPageAsset; + return { pageAsset }; + } catch (error: any) { + if (error?.status === 404) { + return { pageAsset: null, error: null }; + } + + return { pageAsset: null, error }; + } +}; + +const fetchNavData = async (languageId = 1) => { + try { const { entity } = (await client.nav.get({ path: "/", depth: 2, - languageId: pageRequestParams.languageId as number, + languageId, })) as { entity: DotcmsNavigationItem }; - return { pageAsset, nav: entity }; + return { nav: entity }; } catch (error) { - return { error }; + return { nav: null, error }; } }; diff --git a/examples/astro/tsconfig.json b/examples/astro/tsconfig.json index acef73989ca5..7effa155f432 100644 --- a/examples/astro/tsconfig.json +++ b/examples/astro/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "react", + "module": "es2020", "baseUrl": "./", "paths": { "@utils/*": ["src/utils/*"], diff --git a/examples/nextjs/src/app/[[...slug]]/page.js b/examples/nextjs/src/app/[[...slug]]/page.js index a62110805d0f..7fa93580b9dc 100644 --- a/examples/nextjs/src/app/[[...slug]]/page.js +++ b/examples/nextjs/src/app/[[...slug]]/page.js @@ -4,6 +4,7 @@ import { ErrorPage } from "@/components/error"; import { handleVanityUrlRedirect } from "@/utils/vanityUrlHandler"; import { client } from "@/utils/dotcmsClient"; import { getPageRequestParams } from "@dotcms/client"; +import { fetchNavData, fetchPageData } from "@/utils/page.utils"; /** * Generate metadata @@ -36,38 +37,31 @@ export async function generateMetadata({ params, searchParams }) { export default async function Home({ searchParams, params }) { const getPageData = async () => { - try { - const path = params?.slug?.join("/") || "/"; - const pageRequestParams = getPageRequestParams({ - path, - params: searchParams, - }); - const pageAsset = await client.page.get({ - ...pageRequestParams, - depth: 3, - }); - const nav = await client.nav.get({ - path: "/", - depth: 2, - languageId: searchParams.language_id, - }); + const path = params?.slug?.join("/") || "/"; + const pageParams = getPageRequestParams({ + path, + params: searchParams, + }); - return { pageAsset, nav }; - } catch (error) { - return { pageAsset: null, nav: null, error }; - } + const { pageAsset, error: pageError } = await fetchPageData(pageParams); + const { nav, error: navError } = await fetchNavData(pageParams.language_id); + + return { + nav, + pageAsset, + error: pageError || navError, + }; }; const { pageAsset, nav, error } = await getPageData(); + // Move this to MyPage if (error) { return ; } - const { vanityUrl } = pageAsset; - - if (vanityUrl) { - handleVanityUrlRedirect(vanityUrl); + if (pageAsset?.vanityUrl) { + handleVanityUrlRedirect(pageAsset?.vanityUrl); } - return ; + return ; } diff --git a/examples/nextjs/src/components/my-page.js b/examples/nextjs/src/components/my-page.js index f5b19c71e85a..e9f0d33ce5f8 100644 --- a/examples/nextjs/src/components/my-page.js +++ b/examples/nextjs/src/components/my-page.js @@ -18,7 +18,7 @@ import { CustomNoComponent } from "./content-types/empty"; import { usePageAsset } from "../hooks/usePageAsset"; import BlogWithBlockEditor from "./content-types/blog"; -import { DotCmsClient } from "@dotcms/client"; +import NotFound from "@/app/not-found"; /** * Configure experiment settings below. If you are not using experiments, @@ -62,32 +62,34 @@ export function MyPage({ pageAsset, nav }) { pageAsset = usePageAsset(pageAsset); + if (!pageAsset) { + return ; + } + return (
- {pageAsset.layout.header && ( -
- -
+ {pageAsset?.layout.header && ( +
{!!nav && }
)}
- {pageAsset.layout.footer &&
} + {pageAsset?.layout.footer &&
}
); } diff --git a/examples/nextjs/src/hooks/usePageAsset.js b/examples/nextjs/src/hooks/usePageAsset.js index cbda64b4191e..dca69d7e7565 100644 --- a/examples/nextjs/src/hooks/usePageAsset.js +++ b/examples/nextjs/src/hooks/usePageAsset.js @@ -1,17 +1,35 @@ -import { client } from "@/utils/dotcmsClient"; import { useEffect, useState } from "react"; +import { client } from "@/utils/dotcmsClient"; +import { + CUSTOMER_ACTIONS, + isInsideEditor, + postMessageToEditor, +} from "@dotcms/client"; + export const usePageAsset = (currentPageAsset) => { const [pageAsset, setPageAsset] = useState(null); useEffect(() => { + if (!isInsideEditor()) { + return; + } + client.editor.on("changes", (page) => { if (!page) { return; } + setPageAsset(page); }); + // If the page is not found, let the editor know + if (!currentPageAsset) { + postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY }); + + return; + } + return () => { client.editor.off("changes"); }; diff --git a/examples/nextjs/src/utils/page.utils.js b/examples/nextjs/src/utils/page.utils.js new file mode 100644 index 000000000000..a8854a2d01f1 --- /dev/null +++ b/examples/nextjs/src/utils/page.utils.js @@ -0,0 +1,32 @@ +import { client } from "./dotcmsClient"; + +export const fetchPageData = async (params) => { + try { + const pageAsset = await client.page.get({ + ...params, + depth: 3, + }); + + return { pageAsset }; + } catch (error) { + if (error?.status === 404) { + return { pageAsset: null, error: null }; + } + + return { pageAsset: null, error }; + } +}; + +export const fetchNavData = async (languageId = 1) => { + try { + const nav = await client.nav.get({ + path: "/", + depth: 2, + languageId, + }); + + return { nav }; + } catch (error) { + return { nav: null, error }; + } +}; From f0ea22e6f83dc042ebf3fd12c7c796a546329a6e Mon Sep 17 00:00:00 2001 From: Jalinson Diaz Date: Wed, 30 Oct 2024 18:24:02 -0300 Subject: [PATCH 02/11] feat(uve): Support `editContentlet` custom action (#30456) This pull request includes several updates to the `DotEmaDialogComponent` and its related files, focusing on renaming the `payload` property to `actionPayload` and adding a new `clientAction` property. These changes aim to improve code clarity and functionality. ### Updates to `DotEmaDialogComponent`: * Renamed the `payload` property to `actionPayload` across various methods (`addContentlet`, `addForm`, `addWidget`, `editContentlet`, `createContentlet`, `createContentletFromPalette`). [[1]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L96-R112) [[2]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L121-R141) [[3]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L188-R190) [[4]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L202-R209) * Added the `clientAction` property to the component's state and related method calls. [[1]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L337-R340) [[2]](diffhunk://#diff-90ca5d45502430e9bc18da8661aa443a9530d1dfe57c907854decf65176194b0L409-R414) ### Updates to `dot-ema-dialog.component.spec.ts`: * Updated test cases to reflect the renaming of `payload` to `actionPayload` and the addition of `clientAction`. [[1]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4R18) [[2]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L181-R187) [[3]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L203-R210) [[4]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L334-R337) [[5]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L355-R358) [[6]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L382-R385) [[7]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L421-R427) [[8]](diffhunk://#diff-74bc5b082cc3e4a13573517796b104be728b49d58d3cede278110b75cd7944f4L440-R445) ### Updates to `dot-ema-dialog.store.spec.ts`: * Modified test cases to use `actionPayload` instead of `payload` and added checks for the `clientAction` property. [[1]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eR5) [[2]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL47-R52) [[3]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL60-R62) [[4]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL69-R71) [[5]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL85-R92) [[6]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL117-R157) [[7]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL148-R189) [[8]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL162-R200) [[9]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL171-R214) [[10]](diffhunk://#diff-30064cf2e49d8544c8ed19f040b93774175d47edff3b01ce2b7782c3bbcd506eL190-R234) ### Additional notes: * Added a comment in `dot-contentlet.model.ts` to highlight the potential issues with using a flexible type for storing any kind of data and suggested a possible refactor. [[1]](diffhunk://#diff-6ee53bb90f1585590095ab955fc6f356346bf4ce0b4f4919e37a68489d92d48bR1-R2) [[2]](diffhunk://#diff-6ee53bb90f1585590095ab955fc6f356346bf4ce0b4f4919e37a68489d92d48bR41) --- .../src/lib/dot-contentlet.model.ts | 3 + .../dot-ema-dialog.component.spec.ts | 28 ++--- .../dot-ema-dialog.component.ts | 53 ++++---- .../store/dot-ema-dialog.store.spec.ts | 113 ++++++++++++------ .../store/dot-ema-dialog.store.ts | 85 +++++++------ .../dot-ema-shell.component.spec.ts | 31 +++-- .../edit-ema-editor.component.spec.ts | 73 ++++++++--- .../edit-ema-editor.component.ts | 108 ++++++++++------- .../edit-ema/portlet/src/lib/shared/enums.ts | 9 -- .../edit-ema/portlet/src/lib/shared/models.ts | 45 ++++--- .../dot-editable-text.component.spec.ts | 13 +- .../dot-editable-text.component.ts | 9 +- .../dotcms-layout.component.spec.ts | 4 +- .../dotcms-layout/dotcms-layout.component.ts | 4 +- .../libs/sdk/angular/src/lib/utils/index.ts | 13 +- core-web/libs/sdk/client/jest.config.ts | 12 +- core-web/libs/sdk/client/src/index.ts | 8 +- .../src/lib/client/sdk-js-client.spec.ts | 3 +- .../client/src/lib/client/sdk-js-client.ts | 3 +- .../lib/editor/listeners/listeners.spec.ts | 13 +- .../src/lib/editor/listeners/listeners.ts | 74 ++++++------ .../src/lib/editor/models/client.model.ts | 25 +++- .../src/lib/editor/models/listeners.model.ts | 18 ++- .../client/src/lib/editor/sdk-editor-vtl.ts | 9 +- .../client/src/lib/editor/sdk-editor.spec.ts | 39 +++--- .../sdk/client/src/lib/editor/sdk-editor.ts | 27 ++++- core-web/libs/sdk/react/package.json | 2 +- .../DotEditableText/DotEditableText.spec.tsx | 13 +- .../DotEditableText/DotEditableText.tsx | 11 +- .../src/lib/hooks/useDotcmsEditor.spec.ts | 2 +- .../react/src/lib/hooks/useDotcmsEditor.ts | 4 +- .../libs/sdk/react/src/lib/utils/utils.ts | 12 +- .../WEB-INF/velocity/VM_global_library.vm | 3 +- .../webapp/html/js/editor-js/sdk-editor.js | 2 +- .../ext/contentlet/edit_contentlet_js_inc.jsp | 9 +- .../layout/footer/components/blogs.js | 18 ++- .../layout/footer/components/destinations.js | 22 ++-- .../src/components/shared/contentlet.js | 26 ---- .../src/components/shared/contentlets.js | 88 +++++++------- 39 files changed, 617 insertions(+), 417 deletions(-) delete mode 100644 examples/nextjs/src/components/shared/contentlet.js diff --git a/core-web/libs/dotcms-models/src/lib/dot-contentlet.model.ts b/core-web/libs/dotcms-models/src/lib/dot-contentlet.model.ts index bbaaabda9188..77939313c4f8 100644 --- a/core-web/libs/dotcms-models/src/lib/dot-contentlet.model.ts +++ b/core-web/libs/dotcms-models/src/lib/dot-contentlet.model.ts @@ -1,3 +1,5 @@ +// Beware while using this type, since we have a [key: string]: any; it can be used to store any kind of data and you can write wrong properties and it will not fail +// Maybe we need to refactor this to a generic type that extends from unknown when missing the generic type export interface DotCMSContentlet { archived: boolean; baseType: string; @@ -36,6 +38,7 @@ export interface DotCMSContentlet { contentTypeIcon?: string; variant?: string; __icon__?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; } diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.spec.ts index 7ba1beafda77..6cf8e165cb89 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.spec.ts @@ -15,6 +15,7 @@ import { By } from '@angular/platform-browser'; import { MessageService } from 'primeng/api'; import { Dialog } from 'primeng/dialog'; +import { CLIENT_ACTIONS } from '@dotcms/client'; import { DotAlertConfirmService, DotContentTypeService, @@ -178,11 +179,12 @@ describe('DotEmaDialogComponent', () => { event: expect.objectContaining({ isTrusted: false }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); }); @@ -200,11 +202,12 @@ describe('DotEmaDialogComponent', () => { name: NG_CUSTOM_EVENTS.DIALOG_CLOSED } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); }); }); @@ -331,7 +334,7 @@ describe('DotEmaDialogComponent', () => { containerId: PAYLOAD_MOCK.container.identifier, acceptTypes: PAYLOAD_MOCK.container.acceptTypes, language_id: PAYLOAD_MOCK.language_id, - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); }); @@ -352,7 +355,7 @@ describe('DotEmaDialogComponent', () => { containerId: PAYLOAD_MOCK.container.identifier, acceptTypes: DotCMSBaseTypesContentTypes.WIDGET, language_id: PAYLOAD_MOCK.language_id, - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); }); @@ -379,10 +382,7 @@ describe('DotEmaDialogComponent', () => { component.editContentlet(PAYLOAD_MOCK.contentlet); - expect(editContentletSpy).toHaveBeenCalledWith({ - inode: PAYLOAD_MOCK.contentlet.inode, - title: PAYLOAD_MOCK.contentlet.title - }); + expect(editContentletSpy).toHaveBeenCalledWith(PAYLOAD_MOCK.contentlet); }); it('should trigger editVTLContentlet in the store', () => { @@ -418,13 +418,13 @@ describe('DotEmaDialogComponent', () => { component.createContentlet({ url: 'https://demo.dotcms.com/jsp.jsp', contentType: 'test', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); expect(createContentletSpy).toHaveBeenCalledWith({ contentType: 'test', url: 'https://demo.dotcms.com/jsp.jsp', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); }); @@ -437,12 +437,12 @@ describe('DotEmaDialogComponent', () => { component.createContentletFromPalette({ variable: 'test', name: 'test', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); expect(createContentletFromPalletSpy).toHaveBeenCalledWith({ name: 'test', - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, variable: 'test' }); }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.ts index 646167ba28fc..28230b862661 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/dot-ema-dialog.component.ts @@ -40,6 +40,7 @@ import { CreateFromPaletteAction, DialogAction, DotPage, + EditContentletPayload, VTLFile } from '../../shared/models'; import { EmaFormSelectorComponent } from '../ema-form-selector/ema-form-selector.component'; @@ -93,22 +94,22 @@ export class DotEmaDialogComponent { /** * Add contentlet * - * @param {ActionPayload} payload + * @param {ActionPayload} actionPayload * @memberof EditEmaEditorComponent */ - addContentlet(payload: ActionPayload): void { + addContentlet(actionPayload: ActionPayload): void { this.store.addContentlet({ - containerId: payload.container.identifier, - acceptTypes: payload.container.acceptTypes ?? '*', - language_id: payload.language_id, - payload + containerId: actionPayload.container.identifier, + acceptTypes: actionPayload.container.acceptTypes ?? '*', + language_id: actionPayload.language_id, + actionPayload }); } /** * Add Form * - * @param {ActionPayload} _payload + * @param {ActionPayload} actionPayload * @memberof EditEmaEditorComponent */ addForm(payload: ActionPayload): void { @@ -118,29 +119,26 @@ export class DotEmaDialogComponent { /** * Add Widget * - * @param {ActionPayload} payload + * @param {ActionPayload} actionPayload * @memberof EditEmaEditorComponent */ - addWidget(payload: ActionPayload): void { + addWidget(actionPayload: ActionPayload): void { this.store.addContentlet({ - containerId: payload.container.identifier, + containerId: actionPayload.container.identifier, acceptTypes: DotCMSBaseTypesContentTypes.WIDGET, - language_id: payload.language_id, - payload + language_id: actionPayload.language_id, + actionPayload }); } /** * Edit contentlet * - * @param {Partial} contentlet + * @param {EditContentletPayload} contentlet * @memberof DotEmaDialogComponent */ - editContentlet(contentlet: Partial) { - this.store.editContentlet({ - inode: contentlet.inode, - title: contentlet.title - }); + editContentlet(payload: EditContentletPayload) { + this.store.editContentlet(payload); } /** @@ -185,11 +183,11 @@ export class DotEmaDialogComponent { * @param {CreateContentletAction} { url, contentType, payload } * @memberof DotEmaDialogComponent */ - createContentlet({ url, contentType, payload }: CreateContentletAction) { + createContentlet({ url, contentType, actionPayload }: CreateContentletAction) { this.store.createContentlet({ url, contentType, - payload + actionPayload }); } @@ -199,11 +197,16 @@ export class DotEmaDialogComponent { * @param {CreateFromPaletteAction} { variable, name, payload } * @memberof DotEmaDialogComponent */ - createContentletFromPalette({ variable, name, payload, language_id }: CreateFromPaletteAction) { + createContentletFromPalette({ + variable, + name, + actionPayload, + language_id + }: CreateFromPaletteAction) { this.store.createContentletFromPalette({ variable, name, - payload, + actionPayload, language_id }); } @@ -334,7 +337,7 @@ export class DotEmaDialogComponent { case NG_CUSTOM_EVENTS.EDIT_CONTENTLET_UPDATED: { // The edit content emits this for savings when translating a page and does not emit anything when changing the content - if (this.dialogState().editContentForm.isTranslation) { + if (this.dialogState().form.isTranslation) { this.store.setSaved(); if (event.detail.payload.isMoveAction) { @@ -406,8 +409,8 @@ export class DotEmaDialogComponent { } private emitAction(event: CustomEvent) { - const { payload, editContentForm } = this.dialogState(); + const { actionPayload, form, clientAction } = this.dialogState(); - this.action.emit({ event, payload, form: editContentForm }); + this.action.emit({ event, actionPayload, form, clientAction }); } } diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts index c23ce3bb0db1..84966322f09e 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts @@ -2,6 +2,7 @@ import { expect, it, describe } from '@jest/globals'; import { SpectatorService, createServiceFactory } from '@ngneat/spectator/jest'; import { of } from 'rxjs'; +import { CLIENT_ACTIONS } from '@dotcms/client'; import { DotMessageService } from '@dotcms/data-access'; import { MockDotMessageService } from '@dotcms/utils-testing'; @@ -44,10 +45,11 @@ describe('DotEmaDialogStoreService', () => { header: '', type: null, status: DialogStatus.LOADING, - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -57,7 +59,7 @@ describe('DotEmaDialogStoreService', () => { spectator.service.setDirty(); spectator.service.dialogState$.subscribe((state) => { - expect(state.editContentForm.status).toBe(FormStatus.DIRTY); + expect(state.form.status).toBe(FormStatus.DIRTY); done(); }); }); @@ -66,7 +68,7 @@ describe('DotEmaDialogStoreService', () => { spectator.service.setSaved(); spectator.service.dialogState$.subscribe((state) => { - expect(state.editContentForm.status).toBe(FormStatus.SAVED); + expect(state.form.status).toBe(FormStatus.SAVED); done(); }); }); @@ -82,11 +84,12 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.IDLE, header: '', type: null, - payload: undefined, - editContentForm: { + actionPayload: undefined, + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -114,10 +117,44 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP + }); + done(); + }); + }); + + it('should initialize with edit iframe properties and with clientAction', (done) => { + spectator.service.editContentlet({ + inode: '123', + title: 'test', + clientAction: CLIENT_ACTIONS.EDIT_CONTENTLET + }); + + const queryParams = new URLSearchParams({ + p_p_id: 'content', + p_p_action: '1', + p_p_state: 'maximized', + p_p_mode: 'view', + _content_struts_action: '/ext/contentlet/edit_contentlet', + _content_cmd: 'edit', + inode: '123' + }); + + spectator.service.dialogState$.subscribe((state) => { + expect(state).toEqual({ + url: LAYOUT_URL + '?' + queryParams.toString(), + status: DialogStatus.LOADING, + header: 'test', + type: 'content', + form: { + status: FormStatus.PRISTINE, + isTranslation: false + }, + clientAction: CLIENT_ACTIONS.EDIT_CONTENTLET }); done(); }); @@ -145,10 +182,11 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -159,7 +197,7 @@ describe('DotEmaDialogStoreService', () => { containerId: '1234', acceptTypes: 'test', language_id: '1', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); spectator.service.dialogState$.subscribe((state) => { @@ -168,11 +206,12 @@ describe('DotEmaDialogStoreService', () => { header: 'Search Content', type: 'content', status: DialogStatus.LOADING, - payload: PAYLOAD_MOCK, - editContentForm: { + actionPayload: PAYLOAD_MOCK, + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -187,11 +226,12 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, url: null, type: 'form', - payload: PAYLOAD_MOCK, - editContentForm: { + actionPayload: PAYLOAD_MOCK, + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -201,7 +241,7 @@ describe('DotEmaDialogStoreService', () => { spectator.service.createContentlet({ contentType: 'test', url: 'some/really/long/url', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); spectator.service.dialogState$.subscribe((state) => { @@ -210,11 +250,12 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'Create test', type: 'content', - payload: PAYLOAD_MOCK, - editContentForm: { + actionPayload: PAYLOAD_MOCK, + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -224,7 +265,7 @@ describe('DotEmaDialogStoreService', () => { spectator.service.createContentlet({ url: 'some/really/long/url', contentType: 'Blog Posts', - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); spectator.service.dialogState$.subscribe((state) => { @@ -232,7 +273,7 @@ describe('DotEmaDialogStoreService', () => { expect(state.status).toBe(DialogStatus.LOADING); expect(state.url).toBe('some/really/long/url'); expect(state.type).toBe('content'); - expect(state.payload).toEqual(PAYLOAD_MOCK); + expect(state.actionPayload).toEqual(PAYLOAD_MOCK); done(); }); }); @@ -245,7 +286,7 @@ describe('DotEmaDialogStoreService', () => { spectator.service.createContentletFromPalette({ variable: 'blogPost', name: 'Blog', - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, language_id: 2 }); @@ -255,7 +296,7 @@ describe('DotEmaDialogStoreService', () => { expect(state.url).toBe('https://demo.dotcms.com/jsp.jsp'); expect(state.type).toBe('content'); - expect(state.payload).toEqual(PAYLOAD_MOCK); + expect(state.actionPayload).toEqual(PAYLOAD_MOCK); done(); }); @@ -271,10 +312,11 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -292,10 +334,11 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); done(); }); @@ -336,10 +379,11 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: true - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); }); }); @@ -380,10 +424,11 @@ describe('DotEmaDialogStoreService', () => { status: DialogStatus.LOADING, header: 'test', type: 'content', - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: true - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); }); }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts index 1a291858c3f3..b0a2eb001a9e 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts @@ -5,6 +5,7 @@ import { Injectable, inject } from '@angular/core'; import { switchMap } from 'rxjs/operators'; +import { CLIENT_ACTIONS } from '@dotcms/client'; import { DotMessageService } from '@dotcms/data-access'; import { DotActionUrlService } from '../../../services/dot-action-url/dot-action-url.service'; @@ -12,6 +13,7 @@ import { LAYOUT_URL, CONTENTLET_SELECTOR_URL } from '../../../shared/consts'; import { DialogStatus, FormStatus } from '../../../shared/enums'; import { ActionPayload, + AddContentletAction, CreateContentletAction, CreateFromPaletteAction, DotPage, @@ -27,10 +29,11 @@ export class DotEmaDialogStore extends ComponentStore { url: '', type: null, status: DialogStatus.IDLE, - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); } @@ -48,7 +51,7 @@ export class DotEmaDialogStore extends ComponentStore { readonly createContentletFromPalette = this.effect( (contentTypeVariable$: Observable) => { return contentTypeVariable$.pipe( - switchMap(({ name, variable, payload, language_id = 1 }) => { + switchMap(({ name, variable, actionPayload, language_id = 1 }) => { return this.dotActionUrlService .getCreateContentletUrl(variable, language_id) .pipe( @@ -57,7 +60,7 @@ export class DotEmaDialogStore extends ComponentStore { this.createContentlet({ url, contentType: name, - payload + actionPayload }); }, (e) => { @@ -93,11 +96,11 @@ export class DotEmaDialogStore extends ComponentStore { * @memberof DotEmaDialogStore */ readonly createContentlet = this.updater( - (state, { url, contentType, payload }: CreateContentletAction) => { + (state, { url, contentType, actionPayload }: CreateContentletAction) => { return { ...state, url, - payload, + actionPayload, header: this.dotMessageService.get( 'contenttypes.content.create.contenttype', contentType @@ -128,15 +131,18 @@ export class DotEmaDialogStore extends ComponentStore { * * @memberof DotEmaDialogStore */ - readonly editContentlet = this.updater((state, { inode, title }: EditContentletPayload) => { - return { - ...state, - header: title, - status: DialogStatus.LOADING, - type: 'content', - url: this.createEditContentletUrl(inode) - }; - }); + readonly editContentlet = this.updater( + (state, { inode, title, clientAction = CLIENT_ACTIONS.NOOP }: EditContentletPayload) => { + return { + ...state, + clientAction, //In case it is undefined we set it to "noop" + header: title, + status: DialogStatus.LOADING, + type: 'content', + url: this.createEditContentletUrl(inode) + }; + } + ); /** * This method is called when the user clicks on the edit URL Content Map button @@ -170,7 +176,7 @@ export class DotEmaDialogStore extends ComponentStore { status: DialogStatus.LOADING, type: 'content', url: this.createTranslatePageUrl(page, newLanguage), - editContentForm: { + form: { status: FormStatus.PRISTINE, isTranslation: true } @@ -183,26 +189,16 @@ export class DotEmaDialogStore extends ComponentStore { * * @memberof DotEmaDialogStore */ - readonly addContentlet = this.updater( - ( - state, - data: { - containerId: string; - acceptTypes: string; - language_id: string; - payload: ActionPayload; - } - ) => { - return { - ...state, - header: this.dotMessageService.get('edit.ema.page.dialog.header.search.content'), - status: DialogStatus.LOADING, - url: this.createAddContentletUrl(data), - type: 'content', - payload: data.payload - }; - } - ); + readonly addContentlet = this.updater((state, data: AddContentletAction) => { + return { + ...state, + header: this.dotMessageService.get('edit.ema.page.dialog.header.search.content'), + status: DialogStatus.LOADING, + url: this.createAddContentletUrl(data), + type: 'content', + actionPayload: data.actionPayload + }; + }); /** * This method is called when the user make changes in the form @@ -212,8 +208,8 @@ export class DotEmaDialogStore extends ComponentStore { readonly setDirty = this.updater((state) => { return { ...state, - editContentForm: { - ...state.editContentForm, + form: { + ...state.form, status: FormStatus.DIRTY } }; @@ -227,8 +223,8 @@ export class DotEmaDialogStore extends ComponentStore { readonly setSaved = this.updater((state) => { return { ...state, - editContentForm: { - ...state.editContentForm, + form: { + ...state.form, status: FormStatus.SAVED } }; @@ -246,7 +242,7 @@ export class DotEmaDialogStore extends ComponentStore { status: DialogStatus.LOADING, url: null, type: 'form', - payload + actionPayload: payload }; }); @@ -262,11 +258,12 @@ export class DotEmaDialogStore extends ComponentStore { header: '', status: DialogStatus.IDLE, type: null, - payload: undefined, - editContentForm: { + actionPayload: undefined, + form: { status: FormStatus.PRISTINE, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }; }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts index f932e1506a06..d7542cab4a7a 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts @@ -20,6 +20,7 @@ import { ConfirmDialogModule } from 'primeng/confirmdialog'; import { DialogService } from 'primeng/dynamicdialog'; import { ToastModule } from 'primeng/toast'; +import { CLIENT_ACTIONS } from '@dotcms/client'; import { DotContentletLockerService, DotExperimentsService, @@ -829,11 +830,12 @@ describe('DotEmaShellComponent', () => { name: NG_CUSTOM_EVENTS.DIALOG_CLOSED } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.DIRTY, isTranslation: true - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); expect(router.navigate).toHaveBeenCalledWith([], { @@ -871,11 +873,12 @@ describe('DotEmaShellComponent', () => { name: NG_CUSTOM_EVENTS.DIALOG_CLOSED } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.PRISTINE, isTranslation: true - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); expect(router.navigate).toHaveBeenCalledWith([], { @@ -914,11 +917,12 @@ describe('DotEmaShellComponent', () => { name: NG_CUSTOM_EVENTS.DIALOG_CLOSED } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { isTranslation: true, status: FormStatus.SAVED - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); spectator.detectChanges(); @@ -955,11 +959,12 @@ describe('DotEmaShellComponent', () => { } } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.SAVED, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); spectator.detectChanges(); @@ -985,11 +990,12 @@ describe('DotEmaShellComponent', () => { } } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.SAVED, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); spectator.detectChanges(); @@ -1026,11 +1032,12 @@ describe('DotEmaShellComponent', () => { } } }), - payload: PAYLOAD_MOCK, + actionPayload: PAYLOAD_MOCK, form: { status: FormStatus.SAVED, isTranslation: false - } + }, + clientAction: CLIENT_ACTIONS.NOOP }); spectator.detectChanges(); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts index 4a3812a0288a..63e3a32cb453 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.spec.ts @@ -18,7 +18,7 @@ import { ConfirmationService, MessageService } from 'primeng/api'; import { ConfirmDialogModule } from 'primeng/confirmdialog'; import { DialogService } from 'primeng/dynamicdialog'; -import { CUSTOMER_ACTIONS } from '@dotcms/client'; +import { CLIENT_ACTIONS } from '@dotcms/client'; import { DotAlertConfirmService, DotContentTypeService, @@ -600,13 +600,56 @@ describe('EditEmaEditorComponent', () => { ); }); + it('should open a dialog to edit contentlet using custom action and trigger reload after saving', (done) => { + window.dispatchEvent( + new MessageEvent('message', { + origin: HOST, + data: { + action: CLIENT_ACTIONS.EDIT_CONTENTLET, + payload: CONTENTLETS_MOCK[0] + } + }) + ); + + spectator.detectComponentChanges(); + + const dialog = spectator.debugElement.query( + By.css("[data-testId='ema-dialog']") + ); + + const pDialog = dialog.query(By.css('p-dialog')); + + expect(pDialog.attributes['ng-reflect-visible']).toBe('true'); + + const iframe = spectator.debugElement.query(By.css('[data-testId="iframe"]')); + + iframe.nativeElement.contentWindow.addEventListener( + 'message', + (event: MessageEvent) => { + expect(event).toBeTruthy(); + done(); + } + ); + + triggerCustomEvent(dialog, 'action', { + event: new CustomEvent('ng-event', { + detail: { + name: NG_CUSTOM_EVENTS.SAVE_PAGE, + payload: {} + } + }) + }); + + spectator.detectChanges(); + }); + describe('reorder navigation', () => { it('should open a dialog to reorder the navigation', () => { window.dispatchEvent( new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.REORDER_MENU, + action: CLIENT_ACTIONS.REORDER_MENU, payload: { reorderUrl: 'http://localhost:3000/reorder-menu' } @@ -681,7 +724,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.REORDER_MENU, + action: CLIENT_ACTIONS.REORDER_MENU, payload: { reorderUrl: 'http://localhost:3000/reorder-menu' } @@ -954,7 +997,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, payload: { inode: '123' } @@ -1026,7 +1069,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload: PAYLOAD_MOCK + actionPayload: PAYLOAD_MOCK }); spectator.detectChanges(); @@ -1086,7 +1129,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload + actionPayload: payload }); spectator.detectChanges(); @@ -1164,7 +1207,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload + actionPayload: payload }); spectator.detectChanges(); @@ -1245,7 +1288,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload + actionPayload: payload }); spectator.detectChanges(); @@ -1323,7 +1366,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload + actionPayload: payload }); spectator.detectChanges(); @@ -1404,7 +1447,7 @@ describe('EditEmaEditorComponent', () => { } } }), - payload + actionPayload: payload }); spectator.detectChanges(); @@ -2719,7 +2762,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: { dataset: { inode: '123', @@ -2755,7 +2798,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: null } }) @@ -2775,7 +2818,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.CLIENT_READY + action: CLIENT_ACTIONS.CLIENT_READY } }) ); @@ -2799,7 +2842,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.CLIENT_READY, + action: CLIENT_ACTIONS.CLIENT_READY, payload: config } }) @@ -2827,7 +2870,7 @@ describe('EditEmaEditorComponent', () => { new MessageEvent('message', { origin: HOST, data: { - action: CUSTOMER_ACTIONS.CLIENT_READY, + action: CLIENT_ACTIONS.CLIENT_READY, payload: config } }) diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts index 0f826f06f5e5..db7df5131ed4 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts @@ -25,7 +25,7 @@ import { ProgressBarModule } from 'primeng/progressbar'; import { takeUntil, catchError, filter, map, switchMap, tap, take } from 'rxjs/operators'; -import { CUSTOMER_ACTIONS } from '@dotcms/client'; +import { CLIENT_ACTIONS, NOTIFY_CLIENT } from '@dotcms/client'; import { DotMessageService, DotCopyContentService, @@ -69,7 +69,7 @@ import { DotEmaDialogComponent } from '../components/dot-ema-dialog/dot-ema-dial import { DotPageApiService } from '../services/dot-page-api.service'; import { InlineEditService } from '../services/inline-edit/inline-edit.service'; import { DEFAULT_PERSONA, IFRAME_SCROLL_ZONE, WINDOW } from '../shared/consts'; -import { EDITOR_STATE, NG_CUSTOM_EVENTS, NOTIFY_CUSTOMER, UVE_STATUS } from '../shared/enums'; +import { EDITOR_STATE, NG_CUSTOM_EVENTS, UVE_STATUS } from '../shared/enums'; import { ActionPayload, PositionPayload, @@ -78,7 +78,9 @@ import { VTLFile, DeletePayload, InsertPayloadFromDelete, - ReorderPayload + ReorderPayload, + DialogAction, + PostMessage } from '../shared/models'; import { UVEStore } from '../store/dot-uve.store'; import { ClientRequestProps } from '../store/features/client/withClient'; @@ -200,7 +202,12 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { const isDragging = this.uveStore.$editorIsInDraggingState(); if (isDragging) { - this.contentWindow?.postMessage(NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS, this.host); + this.contentWindow?.postMessage( + { + name: NOTIFY_CLIENT.UVE_REQUEST_BOUNDS + }, + this.host + ); } }); @@ -306,7 +313,12 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { } this.uveStore.setEditorState(EDITOR_STATE.DRAGGING); - this.contentWindow?.postMessage(NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS, this.host); + this.contentWindow?.postMessage( + { + name: NOTIFY_CLIENT.UVE_REQUEST_BOUNDS + }, + this.host + ); if (dragItem) { return; @@ -370,7 +382,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.uveStore.updateEditorScrollDragState(); this.contentWindow?.postMessage( - { name: NOTIFY_CUSTOMER.EMA_SCROLL_INSIDE_IFRAME, direction }, + { name: NOTIFY_CLIENT.UVE_SCROLL_INSIDE_IFRAME, direction }, this.host ); }); @@ -533,11 +545,11 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { /** * Handle the custom event * - * @param {{ event: CustomEvent; payload: ActionPayload }} { event, payload } + * @param {DialogAction} * @memberof EditEmaEditorComponent */ - onCustomEvent({ event, payload }: { event: CustomEvent; payload: ActionPayload }) { - this.handleNgEvent({ event, payload })?.(); + onCustomEvent(dialogAction: DialogAction) { + this.handleNgEvent(dialogAction)?.(); } /** @@ -608,10 +620,11 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { return; } else if (dragItem.draggedPayload.type === 'content-type') { this.uveStore.resetEditorProperties(); // In case the user cancels the creation of the contentlet, we already have the editor in idle state + this.dialog.createContentletFromPalette({ ...dragItem.draggedPayload.item, - language_id: this.uveStore.$languageId(), - payload + actionPayload: payload, + language_id: this.uveStore.$languageId() }); } else if (dragItem.draggedPayload.type === 'temp') { const { pageContainers, didInsert } = insertContentletInContainer({ @@ -677,7 +690,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { }); } - protected handleNgEvent({ event, payload }: { event: CustomEvent; payload: ActionPayload }) { + protected handleNgEvent({ event, actionPayload, clientAction }: DialogAction) { const { detail } = event; return ( void>>{ @@ -686,10 +699,9 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { }, [NG_CUSTOM_EVENTS.CONTENT_SEARCH_SELECT]: () => { const { pageContainers, didInsert } = insertContentletInContainer({ - ...payload, + ...actionPayload, newContentletId: detail.data.identifier }); - if (!didInsert) { this.handleDuplicatedContentlet(); @@ -699,7 +711,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.uveStore.savePage(pageContainers); }, [NG_CUSTOM_EVENTS.SAVE_PAGE]: () => { - const { shouldReloadPage, contentletIdentifier } = detail.payload; + const { shouldReloadPage, contentletIdentifier } = detail.payload ?? {}; if (shouldReloadPage) { this.reloadURLContentMapPage(contentletIdentifier); @@ -707,14 +719,23 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { return; } - if (!payload) { + if (clientAction === CLIENT_ACTIONS.EDIT_CONTENTLET) { + this.contentWindow?.postMessage( + { + name: NOTIFY_CLIENT.UVE_RELOAD_PAGE + }, + this.host + ); + } + + if (!actionPayload) { this.uveStore.reload(); return; } const { pageContainers, didInsert } = insertContentletInContainer({ - ...payload, + ...actionPayload, newContentletId: contentletIdentifier }); @@ -730,7 +751,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.dialog.createContentlet({ contentType: detail.data.contentType, url: detail.data.url, - payload + actionPayload }); this.cd.detectChanges(); }, @@ -738,14 +759,14 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { const formId = detail.data.identifier; this.dotPageApiService - .getFormIndetifier(payload.container.identifier, formId) + .getFormIndetifier(actionPayload.container.identifier, formId) .pipe( tap(() => { this.uveStore.setUveStatus(UVE_STATUS.LOADING); }), map((newFormId: string) => { return { - ...payload, + ...actionPayload, newContentletId: newFormId }; }), @@ -799,13 +820,13 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { * Handle the post message event * * @private - * @param {{ action: CUSTOMER_ACTIONS; payload: DotCMSContentlet }} data + * @param {{ action: CLIENT_ACTIONS; payload: DotCMSContentlet }} data * @return {*} * @memberof DotEmaComponent */ - private handlePostMessage({ action, payload }: { action: string; payload: unknown }): void { - const CUSTOMER_ACTIONS_FUNC_MAP = { - [CUSTOMER_ACTIONS.NAVIGATION_UPDATE]: (payload: SetUrlPayload) => { + private handlePostMessage({ action, payload }: PostMessage): void { + const CLIENT_ACTIONS_FUNC_MAP = { + [CLIENT_ACTIONS.NAVIGATION_UPDATE]: (payload: SetUrlPayload) => { // When we set the url, we trigger in the shell component a load to get the new state of the page // This triggers a rerender that makes nextjs to send the set_url again // But this time the params are the same so the shell component wont trigger a load and there we know that the page is loaded @@ -820,10 +841,10 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { }); } }, - [CUSTOMER_ACTIONS.SET_BOUNDS]: (payload: Container[]) => { + [CLIENT_ACTIONS.SET_BOUNDS]: (payload: Container[]) => { this.uveStore.setEditorBounds(payload); }, - [CUSTOMER_ACTIONS.SET_CONTENTLET]: (contentletArea: ClientContentletArea) => { + [CLIENT_ACTIONS.SET_CONTENTLET]: (contentletArea: ClientContentletArea) => { const payload = this.uveStore.getPageSavePayload(contentletArea.payload); this.uveStore.setEditorContentletArea({ @@ -831,19 +852,19 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { payload }); }, - [CUSTOMER_ACTIONS.IFRAME_SCROLL]: () => { + [CLIENT_ACTIONS.IFRAME_SCROLL]: () => { this.uveStore.updateEditorScrollState(); }, - [CUSTOMER_ACTIONS.IFRAME_SCROLL_END]: () => { + [CLIENT_ACTIONS.IFRAME_SCROLL_END]: () => { this.uveStore.updateEditorOnScrollEnd(); }, - [CUSTOMER_ACTIONS.INIT_INLINE_EDITING]: () => { + [CLIENT_ACTIONS.INIT_INLINE_EDITING]: () => { // The iframe says that the editor is ready to start inline editing // The dataset of the inline-editing contentlet is ready inside the service. this.inlineEditingService.initEditor(); this.uveStore.setEditorState(EDITOR_STATE.INLINE_EDITING); }, - [CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING]: (payload: { + [CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING]: (payload: { dataset: InlineEditingContentletDataset; }) => { // The iframe say the contentlet that the content is queue to be inline edited is in multiple pages @@ -886,7 +907,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { if (!this.uveStore.isTraditionalPage()) { const message = { - name: NOTIFY_CUSTOMER.COPY_CONTENTLET_INLINE_EDITING_SUCCESS, + name: NOTIFY_CLIENT.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS, payload: data }; @@ -902,7 +923,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { } }); }, - [CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING]: (payload: UpdatedContentlet) => { + [CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING]: (payload: UpdatedContentlet) => { this.uveStore.setEditorState(EDITOR_STATE.IDLE); // If there is no payload, we don't need to do anything @@ -946,13 +967,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { ) .subscribe(() => this.uveStore.reload()); }, - [CUSTOMER_ACTIONS.REORDER_MENU]: ({ reorderUrl }: ReorderPayload) => { - this.dialog.openDialogOnUrl( - reorderUrl, - this.dotMessageService.get('editpage.content.contentlet.menu.reorder.title') - ); - }, - [CUSTOMER_ACTIONS.CLIENT_READY]: (clientConfig: ClientRequestProps) => { + [CLIENT_ACTIONS.CLIENT_READY]: (clientConfig: ClientRequestProps) => { const { query, params } = clientConfig || {}; const isClientReady = this.uveStore.isClientReady(); @@ -972,11 +987,20 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { this.uveStore.setClientConfiguration({ query, params }); this.uveStore.reload(); }, - [CUSTOMER_ACTIONS.NOOP]: () => { + [CLIENT_ACTIONS.EDIT_CONTENTLET]: (contentlet: DotCMSContentlet) => { + this.dialog.editContentlet({ ...contentlet, clientAction: action }); + }, + [CLIENT_ACTIONS.REORDER_MENU]: ({ reorderUrl }: ReorderPayload) => { + this.dialog.openDialogOnUrl( + reorderUrl, + this.dotMessageService.get('editpage.content.contentlet.menu.reorder.title') + ); + }, + [CLIENT_ACTIONS.NOOP]: () => { /* Do Nothing because is not the origin we are expecting */ } }; - const actionToExecute = CUSTOMER_ACTIONS_FUNC_MAP[action]; + const actionToExecute = CLIENT_ACTIONS_FUNC_MAP[action]; actionToExecute?.(payload); } @@ -988,7 +1012,7 @@ export class EditEmaEditorComponent implements OnInit, OnDestroy { */ reloadIframeContent() { this.iframe?.nativeElement?.contentWindow?.postMessage( - { name: NOTIFY_CUSTOMER.SET_PAGE_DATA, payload: this.uveStore.pageAPIResponse() }, + { name: NOTIFY_CLIENT.UVE_SET_PAGE_DATA, payload: this.uveStore.pageAPIResponse() }, this.host ); } diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/enums.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/enums.ts index 053be21eff33..a060bbb8ac68 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/enums.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/enums.ts @@ -1,12 +1,3 @@ -export enum NOTIFY_CUSTOMER { - EMA_RELOAD_PAGE = 'ema-reload-page', // We need to reload the ema page - EMA_REQUEST_BOUNDS = 'ema-request-bounds', - EMA_EDITOR_PONG = 'ema-editor-pong', - EMA_SCROLL_INSIDE_IFRAME = 'scroll-inside-iframe', - SET_PAGE_DATA = 'SET_PAGE_DATA', - COPY_CONTENTLET_INLINE_EDITING_SUCCESS = 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS' -} - // All the custom events that come from the JSP Iframe export enum NG_CUSTOM_EVENTS { EDIT_CONTENTLET_LOADED = 'edit-contentlet-loaded', diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts index 08d563c447c9..721a2451c10b 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts @@ -1,4 +1,5 @@ -import { DotDevice } from '@dotcms/dotcms-models'; +import { CLIENT_ACTIONS } from '@dotcms/client'; +import { DotCMSContentlet, DotDevice } from '@dotcms/dotcms-models'; import { InfoPage } from '@dotcms/ui'; import { CommonErrors, DialogStatus, FormStatus } from './enums'; @@ -194,12 +195,6 @@ export interface DialogForm { isTranslation: boolean; } -export interface DialogAction { - event: CustomEvent; - payload: ActionPayload; - form: DialogForm; -} - export type DialogType = 'content' | 'form' | 'widget' | null; export interface EditEmaDialogState { @@ -207,25 +202,41 @@ export interface EditEmaDialogState { status: DialogStatus; url: string; type: DialogType; - payload?: ActionPayload; - editContentForm: DialogForm; + actionPayload?: ActionPayload; + form: DialogForm; + clientAction: CLIENT_ACTIONS; +} + +export type DialogActionPayload = Pick; + +export interface DialogAction + extends Pick { + event: CustomEvent; } // We can modify this if we add more events, for now I think is enough -export interface CreateFromPaletteAction { +export interface CreateFromPaletteAction extends DialogActionPayload { variable: string; name: string; - payload: ActionPayload; language_id?: string | number; } -export interface EditContentletPayload { - inode: string; - title: string; -} +export type EditContentletPayload = Partial< + DotCMSContentlet & Pick +>; -export interface CreateContentletAction { +export interface CreateContentletAction extends DialogActionPayload { url: string; contentType: string; - payload: ActionPayload; +} + +export interface AddContentletAction extends DialogActionPayload { + containerId: string; + acceptTypes: string; + language_id: string; +} + +export interface PostMessage { + action: CLIENT_ACTIONS; + payload: unknown; } diff --git a/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts b/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts index 940a8f860d83..20a720041788 100644 --- a/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts +++ b/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts @@ -14,7 +14,7 @@ import { TINYMCE_CONFIG } from './utils'; import { dotcmsContentletMock } from '../../utils/testing.utils'; -const { CUSTOMER_ACTIONS, postMessageToEditor } = dotcmsClient; +const { CLIENT_ACTIONS, postMessageToEditor } = dotcmsClient; // Mock @dotcms/client module jest.mock('@dotcms/client', () => ({ @@ -248,11 +248,12 @@ describe('DotEditableTextComponent', () => { focusSpy = jest.spyOn(spectator.component.editorComponent.editor, 'focus'); }); - it("should focus on the editor when the message is 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { + it("should focus on the editor when the message is 'uve-copy-contentlet-inline-editing-success'", () => { window.dispatchEvent( new MessageEvent('message', { data: { - name: 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS', + name: dotcmsClient.NOTIFY_CLIENT + .UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS, payload: { oldInode: dotcmsContentletMock.inode, inode: dotcmsContentletMock.inode @@ -264,7 +265,7 @@ describe('DotEditableTextComponent', () => { expect(focusSpy).toHaveBeenCalled(); }); - it("should not focus on the editor when the message is not 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { + it("should not focus on the editor when the message is not 'uve-copy-contentlet-inline-editing-success'", () => { window.dispatchEvent( new MessageEvent('message', { data: { name: 'ANOTHER_EVENT' } @@ -312,7 +313,7 @@ describe('DotEditableTextComponent', () => { }; expect(postMessageToEditor).toHaveBeenCalledWith({ - action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, payload }); expect(event.stopPropagation).toHaveBeenCalled(); @@ -401,7 +402,7 @@ describe('DotEditableTextComponent', () => { spectator.triggerEventHandler(editorDebugElement, 'onFocusOut', customEvent); const postMessageData = { - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: { content: 'New content', dataset: { diff --git a/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.ts b/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.ts index 0e50404fb0f2..120db170a31f 100644 --- a/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.ts +++ b/core-web/libs/sdk/angular/src/lib/components/dot-editable-text/dot-editable-text.component.ts @@ -16,9 +16,10 @@ import { import { DomSanitizer } from '@angular/platform-browser'; import { - CUSTOMER_ACTIONS, + CLIENT_ACTIONS, DotCmsClient, isInsideEditor, + NOTIFY_CLIENT, postMessageToEditor } from '@dotcms/client'; @@ -139,7 +140,7 @@ export class DotEditableTextComponent implements OnInit, OnChanges { @HostListener('window:message', ['$event']) onMessage({ data }: MessageEvent) { const { name, payload } = data; - if (name !== 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS') { + if (name !== NOTIFY_CLIENT.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS) { return; } @@ -194,7 +195,7 @@ export class DotEditableTextComponent implements OnInit, OnChanges { try { postMessageToEditor({ - action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, payload: { dataset: { inode, @@ -224,7 +225,7 @@ export class DotEditableTextComponent implements OnInit, OnChanges { try { postMessageToEditor({ - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: { content, dataset: { diff --git a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts index f66d5b427b05..2a5742a064c7 100644 --- a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts +++ b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts @@ -53,7 +53,7 @@ jest.mock('@dotcms/client', () => ({ } } }, - CUSTOMER_ACTIONS: { + CLIENT_ACTIONS: { GET_PAGE_DATA: 'get-page-data' } })); @@ -148,7 +148,7 @@ describe('DotcmsLayoutComponent', () => { it('should post message to editor', () => { spectator.detectChanges(); expect(dotcmsClient.postMessageToEditor).toHaveBeenCalledWith({ - action: dotcmsClient.CUSTOMER_ACTIONS.CLIENT_READY, + action: dotcmsClient.CLIENT_ACTIONS.CLIENT_READY, payload: query }); }); diff --git a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts index 51aeb6d115e5..d94dc0ec2fa4 100644 --- a/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts +++ b/core-web/libs/sdk/angular/src/lib/layout/dotcms-layout/dotcms-layout.component.ts @@ -11,7 +11,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { - CUSTOMER_ACTIONS, + CLIENT_ACTIONS, DotCmsClient, EditorConfig, initEditor, @@ -137,7 +137,7 @@ export class DotcmsLayoutComponent implements OnInit { this.pageContextService.setPageAsset(data as DotCMSPageAsset); }); - postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY, payload: this.editor }); + postMessageToEditor({ action: CLIENT_ACTIONS.CLIENT_READY, payload: this.editor }); } ngOnDestroy() { diff --git a/core-web/libs/sdk/angular/src/lib/utils/index.ts b/core-web/libs/sdk/angular/src/lib/utils/index.ts index fd9f44de7c33..902faf84e3c6 100644 --- a/core-web/libs/sdk/angular/src/lib/utils/index.ts +++ b/core-web/libs/sdk/angular/src/lib/utils/index.ts @@ -64,12 +64,21 @@ export const getContainersData = ( .map((structure) => structure.contentTypeVar) .join(','); - const contentlets = containers[identifier].contentlets[`uuid-${uuid}`]; + // Get the contentlets for "this" container + const contentlets = + containers[identifier].contentlets[`uuid-${uuid}`] ?? + containers[identifier].contentlets[`uuid-dotParser_${uuid}`]; + + if (!contentlets) { + console.warn( + `We couldn't find the contentlets for the container with the identifier ${identifier} and the uuid ${uuid} becareful by adding content to this container.\nWe recommend to change the container in the layout and add the content again.` + ); + } return { ...containers[identifier].container, acceptTypes, - contentlets, + contentlets: contentlets ?? [], variantId }; }; diff --git a/core-web/libs/sdk/client/jest.config.ts b/core-web/libs/sdk/client/jest.config.ts index d82afdf4937a..aaa894ef3dfa 100644 --- a/core-web/libs/sdk/client/jest.config.ts +++ b/core-web/libs/sdk/client/jest.config.ts @@ -2,13 +2,13 @@ export default { displayName: 'sdk-client', preset: '../../../jest.preset.js', - globals: { - 'ts-jest': { - tsconfig: '/tsconfig.spec.json' - } - }, transform: { - '^.+\\.[tj]s$': 'ts-jest' + '^.+\\.[tj]s$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json' + } + ] }, moduleFileExtensions: ['ts', 'js', 'html'], coverageDirectory: '../../../coverage/libs/sdk/client' diff --git a/core-web/libs/sdk/client/src/index.ts b/core-web/libs/sdk/client/src/index.ts index 919b1f1f6981..d95a975f1375 100644 --- a/core-web/libs/sdk/client/src/index.ts +++ b/core-web/libs/sdk/client/src/index.ts @@ -1,12 +1,14 @@ import { ClientConfig, DotCmsClient } from './lib/client/sdk-js-client'; -import { CUSTOMER_ACTIONS, postMessageToEditor } from './lib/editor/models/client.model'; +import { CLIENT_ACTIONS, postMessageToEditor } from './lib/editor/models/client.model'; import { CustomClientParams, DotCMSPageEditorConfig, EditorConfig } from './lib/editor/models/editor.model'; +import { NOTIFY_CLIENT } from './lib/editor/models/listeners.model'; import { destroyEditor, + editContentlet, initEditor, isInsideEditor, updateNavigation @@ -17,9 +19,11 @@ export { graphqlToPageEntity, getPageRequestParams, isInsideEditor, + editContentlet, DotCmsClient, DotCMSPageEditorConfig, - CUSTOMER_ACTIONS, + CLIENT_ACTIONS, + NOTIFY_CLIENT, CustomClientParams, postMessageToEditor, EditorConfig, diff --git a/core-web/libs/sdk/client/src/lib/client/sdk-js-client.spec.ts b/core-web/libs/sdk/client/src/lib/client/sdk-js-client.spec.ts index 97c9cd2a697b..c5ab2c1f25ec 100644 --- a/core-web/libs/sdk/client/src/lib/client/sdk-js-client.spec.ts +++ b/core-web/libs/sdk/client/src/lib/client/sdk-js-client.spec.ts @@ -3,6 +3,7 @@ import { Content } from './content/content-api'; import { ClientConfig, DotCmsClient } from './sdk-js-client'; +import { NOTIFY_CLIENT } from '../editor/models/listeners.model'; import * as dotcmsEditor from '../editor/sdk-editor'; global.fetch = jest.fn(); @@ -272,7 +273,7 @@ describe('DotCmsClient', () => { const mockMessageEvent = { data: { - name: 'SET_PAGE_DATA', + name: NOTIFY_CLIENT.UVE_SET_PAGE_DATA, payload: { some: 'test' } } }; diff --git a/core-web/libs/sdk/client/src/lib/client/sdk-js-client.ts b/core-web/libs/sdk/client/src/lib/client/sdk-js-client.ts index c01378310e0d..84915ed16095 100644 --- a/core-web/libs/sdk/client/src/lib/client/sdk-js-client.ts +++ b/core-web/libs/sdk/client/src/lib/client/sdk-js-client.ts @@ -2,6 +2,7 @@ import { Content } from './content/content-api'; import { ErrorMessages } from './models'; import { DotcmsClientListener } from './models/types'; +import { NOTIFY_CLIENT } from '../editor/models/listeners.model'; import { isInsideEditor } from '../editor/sdk-editor'; export type ClientOptions = Omit; @@ -312,7 +313,7 @@ export class DotCmsClient { if (action === 'changes') { const messageCallback = (event: MessageEvent) => { - if (event.data.name === 'SET_PAGE_DATA') { + if (event.data.name === NOTIFY_CLIENT.UVE_SET_PAGE_DATA) { callbackFn(event.data.payload); } }; diff --git a/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.spec.ts b/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.spec.ts index 4e807cf54e6a..911e6c14a5e2 100644 --- a/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.spec.ts +++ b/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.spec.ts @@ -6,19 +6,24 @@ import { scrollHandler } from './listeners'; -import { CUSTOMER_ACTIONS, postMessageToEditor } from '../models/client.model'; +import { CLIENT_ACTIONS, postMessageToEditor } from '../models/client.model'; jest.mock('../models/client.model', () => ({ postMessageToEditor: jest.fn(), - CUSTOMER_ACTIONS: { + CLIENT_ACTIONS: { NAVIGATION_UPDATE: 'set-url', SET_BOUNDS: 'set-bounds', SET_CONTENTLET: 'set-contentlet', + EDIT_CONTENTLET: 'edit-contentlet', IFRAME_SCROLL: 'scroll', PING_EDITOR: 'ping-editor', CONTENT_CHANGE: 'content-change', GET_PAGE_DATA: 'get-page-data', NOOP: 'noop' + }, + INITIAL_DOT_UVE: { + editContentlet: jest.fn(), + lastScrollYPosition: 0 } })); @@ -72,7 +77,7 @@ describe('listeners', () => { expect(addEventListenerSpy).toHaveBeenCalledWith('pointermove', expect.any(Function)); expect(postMessageToEditor).toHaveBeenCalledWith({ - action: CUSTOMER_ACTIONS.SET_CONTENTLET, + action: CLIENT_ACTIONS.SET_CONTENTLET, payload: { x: expect.any(Number), y: expect.any(Number), @@ -110,7 +115,7 @@ describe('listeners', () => { it('should get page data post message to editor', () => { fetchPageDataFromInsideUVE('some-url'); expect(postMessageToEditor).toHaveBeenCalledWith({ - action: CUSTOMER_ACTIONS.GET_PAGE_DATA, + action: CLIENT_ACTIONS.GET_PAGE_DATA, payload: { pathname: 'some-url' } diff --git a/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.ts b/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.ts index 3a1b7444b795..bec47fdbbd22 100644 --- a/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.ts +++ b/core-web/libs/sdk/client/src/lib/editor/listeners/listeners.ts @@ -1,5 +1,5 @@ -import { CUSTOMER_ACTIONS, postMessageToEditor } from '../models/client.model'; -import { DotCMSPageEditorSubscription, NOTIFY_CUSTOMER } from '../models/listeners.model'; +import { CLIENT_ACTIONS, INITIAL_DOT_UVE, postMessageToEditor } from '../models/client.model'; +import { DotCMSPageEditorSubscription, NOTIFY_CLIENT } from '../models/listeners.model'; import { findVTLData, findDotElement, @@ -8,12 +8,6 @@ import { scrollIsInBottom } from '../utils/editor.utils'; -declare global { - interface Window { - lastScrollYPosition: number; - } -} - /** * Represents an array of DotCMSPageEditorSubscription objects. * Used to store the subscriptions for the editor and unsubscribe later. @@ -33,7 +27,7 @@ function setBounds(): void { const positionData = getPageElementBound(containers); postMessageToEditor({ - action: CUSTOMER_ACTIONS.SET_BOUNDS, + action: CLIENT_ACTIONS.SET_BOUNDS, payload: positionData }); } @@ -45,29 +39,34 @@ function setBounds(): void { * @memberof DotCMSPageEditor */ export function listenEditorMessages(): void { - const messageCallback = (event: MessageEvent) => { - switch (event.data) { - case NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS: { + const messageCallback = ( + event: MessageEvent<{ name: NOTIFY_CLIENT; direction: 'up' | 'down' }> + ) => { + const ACTIONS_NOTIFICATION: { [K in NOTIFY_CLIENT]?: () => void } = { + [NOTIFY_CLIENT.UVE_RELOAD_PAGE]: () => { + window.location.reload(); + }, + [NOTIFY_CLIENT.UVE_REQUEST_BOUNDS]: () => { setBounds(); - break; - } - } - - if (event.data.name === NOTIFY_CUSTOMER.EMA_SCROLL_INSIDE_IFRAME) { - const direction = event.data.direction; - - if ( - (window.scrollY === 0 && direction === 'up') || - (scrollIsInBottom() && direction === 'down') - ) { - // If the iframe scroll is at the top or bottom, do not send anything. - // This avoids losing the scrollend event. - return; + }, + [NOTIFY_CLIENT.UVE_SCROLL_INSIDE_IFRAME]: () => { + const direction = event.data.direction; + + if ( + (window.scrollY === 0 && direction === 'up') || + (scrollIsInBottom() && direction === 'down') + ) { + // If the iframe scroll is at the top or bottom, do not send anything. + // This avoids losing the scrollend event. + return; + } + + const scrollY = direction === 'up' ? -120 : 120; + window.scrollBy({ left: 0, top: scrollY, behavior: 'smooth' }); } + }; - const scrollY = direction === 'up' ? -120 : 120; - window.scrollBy({ left: 0, top: scrollY, behavior: 'smooth' }); - } + ACTIONS_NOTIFICATION[event.data.name]?.(); }; window.addEventListener('message', messageCallback); @@ -128,7 +127,7 @@ export function listenHoveredContentlet(): void { }; postMessageToEditor({ - action: CUSTOMER_ACTIONS.SET_CONTENTLET, + action: CLIENT_ACTIONS.SET_CONTENTLET, payload: { x, y, @@ -158,14 +157,19 @@ export function listenHoveredContentlet(): void { export function scrollHandler(): void { const scrollCallback = () => { postMessageToEditor({ - action: CUSTOMER_ACTIONS.IFRAME_SCROLL + action: CLIENT_ACTIONS.IFRAME_SCROLL }); - window.lastScrollYPosition = window.scrollY; + + // In case it doesn't have a dotUVE object, we create it with the initial values. + window.dotUVE = { + ...(window.dotUVE ?? INITIAL_DOT_UVE), + lastScrollYPosition: window.scrollY + }; }; const scrollEndCallback = () => { postMessageToEditor({ - action: CUSTOMER_ACTIONS.IFRAME_SCROLL_END + action: CLIENT_ACTIONS.IFRAME_SCROLL_END }); }; @@ -196,7 +200,7 @@ export function scrollHandler(): void { */ export function preserveScrollOnIframe(): void { const preserveScrollCallback = () => { - window.scrollTo(0, window.lastScrollYPosition); + window.scrollTo(0, window.dotUVE?.lastScrollYPosition); }; window.addEventListener('load', preserveScrollCallback); @@ -215,7 +219,7 @@ export function preserveScrollOnIframe(): void { */ export function fetchPageDataFromInsideUVE(pathname: string) { postMessageToEditor({ - action: CUSTOMER_ACTIONS.GET_PAGE_DATA, + action: CLIENT_ACTIONS.GET_PAGE_DATA, payload: { pathname } diff --git a/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts b/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts index 0eea789477b4..a0c5fa98ea04 100644 --- a/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts +++ b/core-web/libs/sdk/client/src/lib/editor/models/client.model.ts @@ -1,10 +1,22 @@ +import { editContentlet } from '../sdk-editor'; +declare global { + interface Window { + dotUVE: DotUVE; + } +} + +export const INITIAL_DOT_UVE: DotUVE = { + editContentlet, + lastScrollYPosition: 0 +}; + /** * Actions send to the dotcms editor * * @export * @enum {number} */ -export enum CUSTOMER_ACTIONS { +export enum CLIENT_ACTIONS { /** * Tell the dotcms editor that page change */ @@ -54,6 +66,10 @@ export enum CUSTOMER_ACTIONS { * Tell the editor an user send a graphql query */ CLIENT_READY = 'client-ready', + /** + * Tell the editor to edit a contentlet + */ + EDIT_CONTENTLET = 'edit-contentlet', /** * Tell the editor to do nothing */ @@ -68,7 +84,7 @@ export enum CUSTOMER_ACTIONS { * @interface PostMessageProps */ type PostMessageProps = { - action: CUSTOMER_ACTIONS; + action: CLIENT_ACTIONS; payload?: T; }; @@ -82,3 +98,8 @@ type PostMessageProps = { export function postMessageToEditor(message: PostMessageProps) { window.parent.postMessage(message, '*'); } + +export interface DotUVE { + editContentlet: typeof editContentlet; + lastScrollYPosition: number; +} diff --git a/core-web/libs/sdk/client/src/lib/editor/models/listeners.model.ts b/core-web/libs/sdk/client/src/lib/editor/models/listeners.model.ts index 55557166e01a..768980288ef8 100644 --- a/core-web/libs/sdk/client/src/lib/editor/models/listeners.model.ts +++ b/core-web/libs/sdk/client/src/lib/editor/models/listeners.model.ts @@ -4,23 +4,31 @@ * @export * @enum {number} */ -export enum NOTIFY_CUSTOMER { +export enum NOTIFY_CLIENT { /** * Request to page to reload */ - EMA_RELOAD_PAGE = 'ema-reload-page', + UVE_RELOAD_PAGE = 'uve-reload-page', /** * Request the bounds for the elements */ - EMA_REQUEST_BOUNDS = 'ema-request-bounds', + UVE_REQUEST_BOUNDS = 'uve-request-bounds', /** * Received pong from the editor */ - EMA_EDITOR_PONG = 'ema-editor-pong', + UVE_EDITOR_PONG = 'uve-editor-pong', /** * Received scroll event trigger from the editor */ - EMA_SCROLL_INSIDE_IFRAME = 'scroll-inside-iframe' + UVE_SCROLL_INSIDE_IFRAME = 'uve-scroll-inside-iframe', + /** + * Set the page data + */ + UVE_SET_PAGE_DATA = 'uve-set-page-data', + /** + * Copy contentlet inline editing success + */ + UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS = 'uve-copy-contentlet-inline-editing-success' } type ListenerCallbackMessage = (event: MessageEvent) => void; diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor-vtl.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor-vtl.ts index 71d21c6aada9..339e6aae2a43 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor-vtl.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor-vtl.ts @@ -4,13 +4,7 @@ import { preserveScrollOnIframe, scrollHandler } from './listeners/listeners'; -import { isInsideEditor, addClassToEmptyContentlets } from './sdk-editor'; - -declare global { - interface Window { - lastScrollYPosition: number; - } -} +import { isInsideEditor, addClassToEmptyContentlets, initDotUVE } from './sdk-editor'; /** * This is the main entry point for the SDK VTL. @@ -23,6 +17,7 @@ declare global { * */ if (isInsideEditor()) { + initDotUVE(); listenEditorMessages(); scrollHandler(); preserveScrollOnIframe(); diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts index de014aa7418e..9090ee5c5049 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.spec.ts @@ -4,7 +4,7 @@ import { fetchPageDataFromInsideUVE, scrollHandler } from './listeners/listeners'; -import { postMessageToEditor, CUSTOMER_ACTIONS } from './models/client.model'; +import { postMessageToEditor, CLIENT_ACTIONS } from './models/client.model'; import { addClassToEmptyContentlets, initEditor, @@ -12,18 +12,25 @@ import { updateNavigation } from './sdk-editor'; -jest.mock('./models/client.model', () => ({ - postMessageToEditor: jest.fn(), - CUSTOMER_ACTIONS: { - NAVIGATION_UPDATE: 'set-url', - SET_BOUNDS: 'set-bounds', - SET_CONTENTLET: 'set-contentlet', - IFRAME_SCROLL: 'scroll', - PING_EDITOR: 'ping-editor', - CONTENT_CHANGE: 'content-change', - NOOP: 'noop' - } -})); +jest.mock('./models/client.model', () => { + return { + postMessageToEditor: jest.fn(), + CLIENT_ACTIONS: { + NAVIGATION_UPDATE: 'set-url', + SET_BOUNDS: 'set-bounds', + SET_CONTENTLET: 'set-contentlet', + EDIT_CONTENTLET: 'edit-contentlet', + IFRAME_SCROLL: 'scroll', + PING_EDITOR: 'ping-editor', + CONTENT_CHANGE: 'content-change', + NOOP: 'noop' + }, + INITIAL_DOT_UVE: { + editContentlet: jest.fn(), + lastScrollYPosition: 0 + } + }; +}); jest.mock('./listeners/listeners', () => ({ pingEditor: jest.fn(), @@ -80,7 +87,7 @@ describe('DotCMSPageEditor', () => { it('should update navigation', () => { updateNavigation('/'); expect(postMessageToEditor).toHaveBeenCalledWith({ - action: CUSTOMER_ACTIONS.NAVIGATION_UPDATE, + action: CLIENT_ACTIONS.NAVIGATION_UPDATE, payload: { url: 'index' } @@ -93,6 +100,10 @@ describe('DotCMSPageEditor', () => { expect(listenEditorMessages).toHaveBeenCalled(); expect(listenHoveredContentlet).toHaveBeenCalled(); expect(scrollHandler).toHaveBeenCalled(); + expect(window.dotUVE).toEqual({ + editContentlet: expect.any(Function), + lastScrollYPosition: 0 + }); }); }); diff --git a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts index 578fa6d58b85..02480c0fbbdb 100644 --- a/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts +++ b/core-web/libs/sdk/client/src/lib/editor/sdk-editor.ts @@ -5,9 +5,11 @@ import { scrollHandler, subscriptions } from './listeners/listeners'; -import { CUSTOMER_ACTIONS, postMessageToEditor } from './models/client.model'; +import { CLIENT_ACTIONS, INITIAL_DOT_UVE, postMessageToEditor } from './models/client.model'; import { DotCMSPageEditorConfig } from './models/editor.model'; +import { Contentlet } from '../client/content/shared/types'; + /** * Updates the navigation in the editor. * @@ -18,13 +20,29 @@ import { DotCMSPageEditorConfig } from './models/editor.model'; */ export function updateNavigation(pathname: string): void { postMessageToEditor({ - action: CUSTOMER_ACTIONS.NAVIGATION_UPDATE, + action: CLIENT_ACTIONS.NAVIGATION_UPDATE, payload: { url: pathname === '/' ? 'index' : pathname?.replace('/', '') } }); } +/** + * You can use this function to edit a contentlet in the editor. + * + * Calling this function inside the editor, will prompt the UVE to open a dialog to edit the contentlet. + * + * @export + * @template T + * @param {Contentlet} contentlet - The contentlet to edit. + */ +export function editContentlet(contentlet: Contentlet) { + postMessageToEditor({ + action: CLIENT_ACTIONS.EDIT_CONTENTLET, + payload: contentlet + }); +} + /** * Checks if the code is running inside an editor. * @@ -46,6 +64,10 @@ export function isInsideEditor(): boolean { return window.parent !== window; } +export function initDotUVE() { + window.dotUVE = INITIAL_DOT_UVE; +} + /** * Initializes the DotCMS page editor. * @@ -57,6 +79,7 @@ export function isInsideEditor(): boolean { * ``` */ export function initEditor(config: DotCMSPageEditorConfig): void { + initDotUVE(); fetchPageDataFromInsideUVE(config.pathname); listenEditorMessages(); listenHoveredContentlet(); diff --git a/core-web/libs/sdk/react/package.json b/core-web/libs/sdk/react/package.json index 402108929fee..852b3da3b54e 100644 --- a/core-web/libs/sdk/react/package.json +++ b/core-web/libs/sdk/react/package.json @@ -4,7 +4,7 @@ "peerDependencies": { "react": ">=18", "react-dom": ">=18", - "@dotcms/client": "0.0.1-alpha.38", + "@dotcms/client": "latest", "@tinymce/tinymce-react": "^5.1.1" }, "description": "Official React Components library to render a dotCMS page.", diff --git a/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.spec.tsx b/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.spec.tsx index 0aaa79b19335..7ea7ab2c9c89 100644 --- a/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.spec.tsx +++ b/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.spec.tsx @@ -8,7 +8,7 @@ import { DotEditableText } from './DotEditableText'; import { dotcmsContentletMock } from '../../mocks/mockPageContext'; -const { CUSTOMER_ACTIONS, postMessageToEditor } = dotcmsClient; +const { CLIENT_ACTIONS, postMessageToEditor } = dotcmsClient; // Define mockEditor before using it in jest.mock const TINYMCE_EDITOR_MOCK = { @@ -106,11 +106,12 @@ describe('DotEditableText', () => { focusSpy = jest.spyOn(TINYMCE_EDITOR_MOCK, 'focus'); }); - it("should focus on the editor when the message is 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { + it("should focus on the editor when the message is 'UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { window.dispatchEvent( new MessageEvent('message', { data: { - name: 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS', + name: dotcmsClient.NOTIFY_CLIENT + .UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS, payload: { oldInode: dotcmsContentletMock['inode'], inode: '456' @@ -121,7 +122,7 @@ describe('DotEditableText', () => { expect(focusSpy).toHaveBeenCalled(); }); - it("should not focus on the editor when the message is not 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { + it("should not focus on the editor when the message is not 'UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS'", () => { window.dispatchEvent( new MessageEvent('message', { data: { name: 'ANOTHER_EVENT' } @@ -155,7 +156,7 @@ describe('DotEditableText', () => { } }; expect(postMessageToEditor).toHaveBeenCalledWith({ - action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, payload }); }); @@ -209,7 +210,7 @@ describe('DotEditableText', () => { fireEvent(editorElem, event); const postMessageData = { - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: { content: 'New content', dataset: { diff --git a/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.tsx b/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.tsx index 11533db0ea34..9104c7a3e6eb 100644 --- a/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.tsx +++ b/core-web/libs/sdk/react/src/lib/components/DotEditableText/DotEditableText.tsx @@ -4,8 +4,9 @@ import { useEffect, useRef, useState } from 'react'; import { isInsideEditor as isInsideEditorFn, postMessageToEditor, - CUSTOMER_ACTIONS, - DotCmsClient + CLIENT_ACTIONS, + DotCmsClient, + NOTIFY_CLIENT } from '@dotcms/client'; import { DotEditableTextProps, TINYMCE_CONFIG } from './utils'; @@ -79,7 +80,7 @@ export function DotEditableText({ const onMessage = ({ data }: MessageEvent) => { const { name, payload } = data; - if (name !== 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS') { + if (name !== NOTIFY_CLIENT.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS) { return; } @@ -111,7 +112,7 @@ export function DotEditableText({ event.preventDefault(); postMessageToEditor({ - action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.COPY_CONTENTLET_INLINE_EDITING, payload: { dataset: { inode, @@ -131,7 +132,7 @@ export function DotEditableText({ } postMessageToEditor({ - action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, + action: CLIENT_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING, payload: { content: editedContent, dataset: { diff --git a/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.spec.ts b/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.spec.ts index 42cd0beaa285..f5585df64a44 100644 --- a/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.spec.ts +++ b/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.spec.ts @@ -147,7 +147,7 @@ describe('useDotcmsEditor', () => { ); expect(sdkClient.postMessageToEditor).toHaveBeenCalledWith({ - action: sdkClient.CUSTOMER_ACTIONS.CLIENT_READY, + action: sdkClient.CLIENT_ACTIONS.CLIENT_READY, payload: editor }); }); diff --git a/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.ts b/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.ts index 418592a9d18b..04155f8df296 100644 --- a/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.ts +++ b/core-web/libs/sdk/react/src/lib/hooks/useDotcmsEditor.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { - CUSTOMER_ACTIONS, + CLIENT_ACTIONS, DotCmsClient, destroyEditor, initEditor, @@ -69,7 +69,7 @@ export const useDotcmsEditor = ({ pageContext, config }: DotcmsPageProps) => { return; } - postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY, payload: editor }); + postMessageToEditor({ action: CLIENT_ACTIONS.CLIENT_READY, payload: editor }); }, [pathname, editor]); /** diff --git a/core-web/libs/sdk/react/src/lib/utils/utils.ts b/core-web/libs/sdk/react/src/lib/utils/utils.ts index ae8737ed78de..3f673e386491 100644 --- a/core-web/libs/sdk/react/src/lib/utils/utils.ts +++ b/core-web/libs/sdk/react/src/lib/utils/utils.ts @@ -53,12 +53,20 @@ export const getContainersData = ( const acceptTypes = containerStructures.map((structure) => structure.contentTypeVar).join(','); // Get the contentlets for "this" container - const contentlets = containers[identifier].contentlets[`uuid-${uuid}`]; + const contentlets = + containers[identifier].contentlets[`uuid-${uuid}`] ?? + containers[identifier].contentlets[`uuid-dotParser_${uuid}`]; + + if (!contentlets) { + console.warn( + `We couldn't find the contentlets for the container with the identifier ${identifier} and the uuid ${uuid} becareful by adding content to this container.\nWe recommend to change the container in the layout and add the content again.` + ); + } return { ...containers[identifier].container, acceptTypes, - contentlets, + contentlets: contentlets ?? [], variantId }; }; diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm index 0f4d7d4e2000..53c06573d61e 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/VM_global_library.vm @@ -65,13 +65,14 @@ #set($_hasPermission = $contents.doesUserHasPermission($CONTENT_INODE, 2, $EDIT_MODE)) #if($EDIT_MODE && $_hasPermission) #set($localContent = $dotcontent.find($!{CONTENT_INODE})) + #set($jsonContent = $json.generate($localContent)) #end #end diff --git a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js index 3f13c04df996..853270c30ed4 100644 --- a/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js +++ b/dotCMS/src/main/webapp/html/js/editor-js/sdk-editor.js @@ -1 +1 @@ -function i(t){window.parent.postMessage(t,"*")}function E(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:p(n)}),contentlets:N(e,o)}})}function N(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):a(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function p(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function a(t){let n=t.closest('[data-dot-object="container"]');return n?p(n):(console.warn("No container found for the contentlet"),null)}function s(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:s(t?.parentElement):null}function u(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function f(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function h(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=E(t);i({action:"set-bounds",payload:n})}function l(){let t=n=>{switch(n.data){case"ema-request-bounds":{h();break}}if(n.data.name==="scroll-inside-iframe"){let e=n.data.direction;if(window.scrollY===0&&e==="up"||f()&&e==="down")return;let o=e==="up"?-120:120;window.scrollBy({left:0,top:o,behavior:"smooth"})}};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function d(){let t=n=>{let e=s(n.target);if(!e)return;let{x:o,y,width:L,height:v}=e.getBoundingClientRect(),b=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},w={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},M=u(e),D={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):a(e),contentlet:b?P:w,vtlFiles:M};i({action:"set-contentlet",payload:{x:o,y,width:L,height:v,payload:D}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.lastScrollYPosition=window.scrollY},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function m(){let t=()=>{window.scrollTo(0,window.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}function g(){return typeof window>"u"?!1:window.parent!==window}function T(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}g()&&(l(),c(),m(),d(),T()); +function u(t){i({action:"edit-contentlet",payload:t})}function T(){return typeof window>"u"?!1:window.parent!==window}function f(){window.dotUVE=a}function m(){document.querySelectorAll('[data-dot-object="contentlet"]').forEach(n=>{n.clientHeight||n.classList.add("empty-contentlet")})}var a={editContentlet:u,lastScrollYPosition:0};function i(t){window.parent.postMessage(t,"*")}function g(t){return t.map(n=>{let e=n.getBoundingClientRect(),o=Array.from(n.querySelectorAll('[data-dot-object="contentlet"]'));return{x:e.x,y:e.y,width:e.width,height:e.height,payload:JSON.stringify({container:v(n)}),contentlets:I(e,o)}})}function I(t,n){return n.map(e=>{let o=e.getBoundingClientRect();return{x:0,y:o.y-t.y,width:o.width,height:o.height,payload:JSON.stringify({container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:{identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType}})}})}function v(t){return{acceptTypes:t.dataset?.dotAcceptTypes||"",identifier:t.dataset?.dotIdentifier||"",maxContentlets:t.dataset?.maxContentlets||"",uuid:t.dataset?.dotUuid||""}}function E(t){let n=t.closest('[data-dot-object="container"]');return n?v(n):(console.warn("No container found for the contentlet"),null)}function p(t){return t?t?.dataset?.dotObject==="contentlet"||t?.dataset?.dotObject==="container"&&t.children.length===0?t:p(t?.parentElement):null}function y(t){let n=t.querySelectorAll('[data-dot-object="vtl-file"]');return n.length?Array.from(n).map(e=>({inode:e.dataset?.dotInode,name:e.dataset?.dotUrl})):null}function _(){let t=document.documentElement.scrollHeight,n=window.innerHeight;return window.scrollY+n>=t}var r=[];function h(){let t=Array.from(document.querySelectorAll('[data-dot-object="container"]')),n=g(t);i({action:"set-bounds",payload:n})}function d(){let t=n=>{({"uve-reload-page":()=>{window.location.reload()},"uve-request-bounds":()=>{h()},"uve-scroll-inside-iframe":()=>{let o=n.data.direction;if(window.scrollY===0&&o==="up"||_()&&o==="down")return;let s=o==="up"?-120:120;window.scrollBy({left:0,top:s,behavior:"smooth"})}})[n.data.name]?.()};window.addEventListener("message",t),r.push({type:"listener",event:"message",callback:t})}function l(){let t=n=>{let e=p(n.target);if(!e)return;let{x:o,y:s,width:C,height:M}=e.getBoundingClientRect(),w=e.dataset?.dotObject==="container",P={identifier:"TEMP_EMPTY_CONTENTLET",title:"TEMP_EMPTY_CONTENTLET",contentType:"TEMP_EMPTY_CONTENTLET_TYPE",inode:"TEMPY_EMPTY_CONTENTLET_INODE",widgetTitle:"TEMP_EMPTY_CONTENTLET",baseType:"TEMP_EMPTY_CONTENTLET",onNumberOfPages:1},b={identifier:e.dataset?.dotIdentifier,title:e.dataset?.dotTitle,inode:e.dataset?.dotInode,contentType:e.dataset?.dotType,baseType:e.dataset?.dotBasetype,widgetTitle:e.dataset?.dotWidgetTitle,onNumberOfPages:e.dataset?.dotOnNumberOfPages},L=y(e),O={container:e.dataset?.dotContainer?JSON.parse(e.dataset?.dotContainer):E(e),contentlet:w?P:b,vtlFiles:L};i({action:"set-contentlet",payload:{x:o,y:s,width:C,height:M,payload:O}})};document.addEventListener("pointermove",t),r.push({type:"listener",event:"pointermove",callback:t})}function c(){let t=()=>{i({action:"scroll"}),window.dotUVE={...window.dotUVE??a,lastScrollYPosition:window.scrollY}},n=()=>{i({action:"scroll-end"})};window.addEventListener("scroll",t),window.addEventListener("scrollend",n),r.push({type:"listener",event:"scroll",callback:n}),r.push({type:"listener",event:"scroll",callback:t})}function D(){let t=()=>{window.scrollTo(0,window.dotUVE?.lastScrollYPosition)};window.addEventListener("load",t),r.push({type:"listener",event:"scroll",callback:t})}T()&&(f(),d(),c(),D(),l(),m()); diff --git a/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet_js_inc.jsp b/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet_js_inc.jsp index 457c03623601..4c3d52a6ac10 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet_js_inc.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet_js_inc.jsp @@ -453,8 +453,15 @@ * This is beacuse we may need to redirect the user to the new URLMap contentlet. * We need to wait until the re-index process is done to avoid a 404 error. * More info: https://github.com/dotCMS/core/issues/21818 + * + * We also need to wait for the reindex when we edit in order to reload the page when editing using the + * #editContentlet() macro + * More info: https://github.com/dotCMS/core/issues/30218 + * + * Maybe we can avoid this after this is merged: https://github.com/dotCMS/core/pull/30110 + * */ - const newSaveContentCallBack = isURLMapContent ? (data) => setTimeout(() => saveContentCallback(data), 1800) : saveContentCallback; + const newSaveContentCallBack = (data) => setTimeout(() => saveContentCallback(data), 1800); ContentletAjax.saveContent(fmData, isAutoSave, isCheckin, publish, newSaveContentCallBack); } diff --git a/examples/nextjs/src/components/layout/footer/components/blogs.js b/examples/nextjs/src/components/layout/footer/components/blogs.js index c69db89bcf6c..3b4fdf97784b 100644 --- a/examples/nextjs/src/components/layout/footer/components/blogs.js +++ b/examples/nextjs/src/components/layout/footer/components/blogs.js @@ -1,18 +1,18 @@ -import { useEffect, useState } from "react"; -import Contentlets from "@/components/shared/contentlets"; -import { client } from "@/utils/dotcmsClient"; +import { useEffect, useState } from 'react'; +import Contentlets from '@/components/shared/contentlets'; +import { client } from '@/utils/dotcmsClient'; export default function Blogs() { const [blogs, setBlogs] = useState([]); useEffect(() => { client.content - .getCollection("Blog") + .getCollection('Blog') .sortBy([ { - field: "modDate", - order: "desc", - }, + field: 'modDate', + order: 'desc' + } ]) .limit(3) .then((response) => { @@ -25,9 +25,7 @@ export default function Blogs() { return (
-

- Latest Blog Posts -

+

Latest Blog Posts

{!!blogs.length && }
); diff --git a/examples/nextjs/src/components/layout/footer/components/destinations.js b/examples/nextjs/src/components/layout/footer/components/destinations.js index abe53e24c8c6..f1f14ddcc505 100644 --- a/examples/nextjs/src/components/layout/footer/components/destinations.js +++ b/examples/nextjs/src/components/layout/footer/components/destinations.js @@ -1,18 +1,18 @@ -import { useEffect, useState } from "react"; -import Contentlets from "@/components/shared/contentlets"; -import { client } from "@/utils/dotcmsClient"; +import { useEffect, useState } from 'react'; +import Contentlets from '@/components/shared/contentlets'; +import { client } from '@/utils/dotcmsClient'; export default function Destinations() { const [destinations, setDestinations] = useState([]); useEffect(() => { client.content - .getCollection("Destination") + .getCollection('Destination') .sortBy([ { - field: "modDate", - order: "desc", - }, + field: 'modDate', + order: 'desc' + } ]) .limit(3) .then((response) => { @@ -25,12 +25,8 @@ export default function Destinations() { return (
-

- Popular Destinations -

- {!!destinations.length && ( - - )} +

Popular Destinations

+ {!!destinations.length && }
); } diff --git a/examples/nextjs/src/components/shared/contentlet.js b/examples/nextjs/src/components/shared/contentlet.js deleted file mode 100644 index c46ea034ded7..000000000000 --- a/examples/nextjs/src/components/shared/contentlet.js +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; -import { useMemo } from "react"; -import { isInsideEditor } from "@dotcms/client"; - -function Contentlet({ contentlet, children }) { - const insideEditor = useMemo(isInsideEditor, []); - - return insideEditor ? ( -
- {children} -
- ) : ( - children - ); -} - -export default Contentlet; diff --git a/examples/nextjs/src/components/shared/contentlets.js b/examples/nextjs/src/components/shared/contentlets.js index 7582f77e822f..1ea66565e9fa 100644 --- a/examples/nextjs/src/components/shared/contentlets.js +++ b/examples/nextjs/src/components/shared/contentlets.js @@ -1,54 +1,60 @@ -"use client"; -import React from "react"; -import Image from "next/image"; -import Contentlet from "./contentlet"; +'use client'; +import React from 'react'; +import Image from 'next/image'; +import { editContentlet } from '@dotcms/client'; const dateFormatOptions = { - year: "numeric", - month: "long", - day: "numeric", + year: 'numeric', + month: 'long', + day: 'numeric' }; function Contentlets({ contentlets }) { return (
+ ))} ); From c0a01e69bf872ffcb19935214f09eeeb4e26421f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Enrique=20Colina=20Rodr=C3=ADguez?= Date: Thu, 31 Oct 2024 12:41:21 +0100 Subject: [PATCH 03/11] fix(deployment): Publish Starter deployment failure due to incorrect credentials (#30482) (#30509) ### Proposed Changes * Fixing all the environment references to 'starter'. * A new option to include or not old assets. ### Additional Info Related to #30482 (Publish Starter deployment failure due to incorrect credentials). --- .../workflows/cicd_manual_publish-starter.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cicd_manual_publish-starter.yml b/.github/workflows/cicd_manual_publish-starter.yml index d6292a25e276..649338e9aab9 100644 --- a/.github/workflows/cicd_manual_publish-starter.yml +++ b/.github/workflows/cicd_manual_publish-starter.yml @@ -9,6 +9,10 @@ on: options: - 'full' - 'empty' + old-assets: + description: 'Include old assets' + required: true + type: boolean changelog: description: 'Changes description' required: true @@ -28,7 +32,7 @@ env: EMPTY_STARTER_TOKEN: ${{ secrets.DOT_EMPTY_STARTER_ACCESS_TOKEN }} FULL_STARTER_URL: ${{ vars.DOT_STARTER_URL }} FULL_STARTER_TOKEN: ${{ secrets.DOT_STARTER_ACCESS_TOKEN }} - DOWNLOAD_ENDPOINT: api/v1/maintenance/_downloadStarterWithAssets?oldAssets=false + DOWNLOAD_ENDPOINT: api/v1/maintenance/_downloadStarterWithAssets?oldAssets=${{ github.event.inputs.old-assets }} jobs: get-starter: @@ -88,7 +92,7 @@ jobs: deploy-artifacts: needs: [ get-starter ] runs-on: ubuntu-20.04 - environment: trunk + environment: starter outputs: filename: ${{ steps.deploy-artifacts.outputs.filename }} url: ${{ steps.deploy-artifacts.outputs.url }} @@ -153,10 +157,10 @@ jobs: echo "::endgroup::" update-pom: - if: ${{ github.event.inputs.type == 'empty' && github.event.inputs.dry-run == false }} + if: ${{ github.event.inputs.type == 'empty' && github.event.inputs.dry-run == 'false' }} needs: [ deploy-artifacts ] runs-on: ubuntu-20.04 - environment: trunk + environment: starter outputs: pull-request-url: ${{ steps.create-pull-request.outputs.pull-request-url }} steps: @@ -201,10 +205,9 @@ jobs: automated pr send-notification: - needs: [ deploy-artifacts, update-pom ] + needs: [ deploy-artifacts ] runs-on: ubuntu-20.04 - environment: trunk - if: always() && github.event.inputs.dry-run == false + if: always() && github.event.inputs.dry-run == 'false' steps: - uses: actions/checkout@v4 @@ -215,6 +218,7 @@ jobs: echo "::group::Compose Message" ARTIFACT_FILENAME="${{ needs.deploy-artifacts.outputs.filename }}" ARTIFACT_URL="${{ needs.deploy-artifacts.outputs.url }}" + OLD_ASSETS="${{ github.event.inputs.old-assets }}" CHANGELOG="${{ github.event.inputs.changelog }}" PULL_REQUEST_URL="${{ needs.update-pom.outputs.pull-request-url }}" if [ "$STARTER_TYPE" == "empty" ]; then @@ -226,6 +230,7 @@ jobs: > This automated script is happy to announce that a new *_${STARTER_TYPE} starter_* :package: \`${ARTIFACT_FILENAME}\` is now available on \`ARTIFACTORY\` :frog:! > > :link: ${ARTIFACT_URL} + > _Old assets included_: ${OLD_ASSETS} > *Changelog* > \`\`\`${CHANGELOG}\`\`\` > From 98b243969fcd81405c8d39cab69cc05546b31b55 Mon Sep 17 00:00:00 2001 From: Jose Castro Date: Thu, 31 Oct 2024 09:40:49 -0600 Subject: [PATCH 04/11] chore(Telemetry) #30079 : Move telemetry plugin into core - Part 1 (#30520) ### Proposed Changes * Migrates all the code from the `Telemetry` plug-in into our `core` project. * This is the first part of the process, so it just takes the code "as is" from the plugin, and places it inside the `core` project. It only includes a few adjustments on some Javadoc, code formatting, and the addition of the `toString()` method in a few classes. * These changes can safely co-exist with the current `Telemetry` plugin. * In order to have a more effective Code Review process, the goal is to have two pull requests: * The first one with the existing code from the plugin -- this one. * The second one with the code changes in `core` that effectively add the REST Endpoint, Web Interceptor, and Quartz Job which are currently being added via the `Activator` class. --- .../java/com/dotcms/telemetry/Metric.java | 83 +++++ .../telemetry/MetricCalculationError.java | 35 +++ .../com/dotcms/telemetry/MetricCategory.java | 27 ++ .../com/dotcms/telemetry/MetricFeature.java | 20 ++ .../java/com/dotcms/telemetry/MetricType.java | 59 ++++ .../com/dotcms/telemetry/MetricValue.java | 62 ++++ .../com/dotcms/telemetry/MetricsSnapshot.java | 93 ++++++ .../business/MetricEndpointPayload.java | 125 ++++++++ .../telemetry/business/MetricFactory.java | 77 +++++ .../dotcms/telemetry/business/MetricsAPI.java | 259 ++++++++++++++++ .../telemetry/collectors/DBMetricType.java | 30 ++ .../collectors/MetricStatsCollector.java | 289 ++++++++++++++++++ .../collectors/api/ApiMetricAPI.java | 107 +++++++ .../collectors/api/ApiMetricFactory.java | 180 +++++++++++ .../api/ApiMetricFactorySubmitter.java | 68 +++++ .../collectors/api/ApiMetricRequest.java | 70 +++++ .../collectors/api/ApiMetricType.java | 114 +++++++ .../collectors/api/ApiMetricTypes.java | 63 ++++ .../api/ApiMetricWebInterceptor.java | 161 ++++++++++ .../collectors/api/RequestHashCalculator.java | 192 ++++++++++++ ...ontainersInLivePageDatabaseMetricType.java | 47 +++ ...nersInLiveTemplatesDatabaseMetricType.java | 62 ++++ ...ontainersInTemplateDatabaseMetricType.java | 115 +++++++ ...ainersInWorkingPageDatabaseMetricType.java | 89 ++++++ ...ontainersInLivePageDatabaseMetricType.java | 25 ++ ...nersInLiveTemplatesDatabaseMetricType.java | 24 ++ ...ainersInWorkingPageDatabaseMetricType.java | 25 ++ ...ontainersInLivePageDatabaseMetricType.java | 25 ++ ...nersInLiveTemplatesDatabaseMetricType.java | 24 ++ ...ainersInWorkingPageDatabaseMetricType.java | 24 ++ .../LastContentEditedDatabaseMetricType.java | 35 +++ ...ultLanguageContentsDatabaseMetricType.java | 38 +++ ...centlyEditedContentDatabaseMetricType.java | 37 +++ .../TotalContentsDatabaseMetricType.java | 35 +++ ...ultLanguageContentsDatabaseMetricType.java | 44 +++ .../ContentTypeFieldsMetricType.java | 64 ++++ .../CountOfBinaryFieldsMetricType.java | 19 ++ .../CountOfBlockEditorFieldsMetricType.java | 19 ++ .../CountOfCategoryFieldsMetricType.java | 19 ++ .../CountOfCheckboxFieldsMetricType.java | 19 ++ .../CountOfColumnsFieldsMetricType.java | 19 ++ .../CountOfConstantFieldsMetricType.java | 20 ++ .../CountOfDateFieldsMetricType.java | 20 ++ .../CountOfDateTimeFieldsMetricType.java | 19 ++ .../CountOfFileFieldsMetricType.java | 19 ++ .../CountOfHiddenFieldsMetricType.java | 20 ++ .../CountOfImageFieldsMetricType.java | 19 ++ .../CountOfJSONFieldsMetricType.java | 20 ++ .../CountOfKeyValueFieldsMetricType.java | 20 ++ .../CountOfLineDividersFieldsMetricType.java | 19 ++ .../CountOfMultiselectFieldsMetricType.java | 19 ++ .../CountOfPermissionsFieldsMetricType.java | 19 ++ .../CountOfRadioFieldsMetricType.java | 19 ++ .../CountOfRelationshipFieldsMetricType.java | 19 ++ .../CountOfRowsFieldsMetricType.java | 19 ++ .../CountOfSelectFieldsMetricType.java | 19 ++ .../CountOfSiteOrFolderFieldsMetricType.java | 19 ++ .../CountOfTabFieldsMetricType.java | 19 ++ .../CountOfTagFieldsMetricType.java | 19 ++ .../CountOfTextAreaFieldsMetricType.java | 19 ++ .../CountOfTextFieldsMetricType.java | 19 ++ .../CountOfTimeFieldsMetricType.java | 19 ++ .../CountOfWYSIWYGFieldsMetricType.java | 19 ++ .../CountOfContentAssetImageBEAPICalls.java | 58 ++++ .../CountOfContentAssetImageFEAPICalls.java | 58 ++++ .../image/CountOfDAImageBEAPICalls.java | 57 ++++ .../image/CountOfDAImageFEAPICalls.java | 57 ++++ ...ngeDefaultLanguagesDatabaseMetricType.java | 36 +++ .../OldStyleLanguagesVarialeMetricType.java | 56 ++++ .../TotalLanguagesDatabaseMetricType.java | 35 +++ ...eLanguagesVariablesDatabaseMetricType.java | 39 +++ ...otalUniqueLanguagesDatabaseMetricType.java | 37 +++ ...gLanguagesVariablesDatabaseMetricType.java | 44 +++ ...fLiveSitesWithSiteVariablesMetricType.java | 16 + ...esWithIndividualPermissionsMetricType.java | 43 +++ ...untOfSitesWithSiteVariablesMetricType.java | 74 +++++ .../CountOfSitesWithThumbnailsMetricType.java | 84 +++++ ...rkingSitesWithSiteVariablesMetricType.java | 16 + ...NoDefaultTagStorageDatabaseMetricType.java | 49 +++ ...sWithNoSystemFieldsDatabaseMetricType.java | 40 +++ ...tesWithRunDashboardDatabaseMetricType.java | 40 +++ .../TotalActiveSitesDatabaseMetricType.java | 40 +++ ...lAliasesActiveSitesDatabaseMetricType.java | 43 +++ ...otalAliasesAllSitesDatabaseMetricType.java | 43 +++ .../site/TotalSitesDatabaseMetricType.java | 35 +++ .../CountSiteSearchDocumentMetricType.java | 32 ++ .../CountSiteSearchIndicesMetricType.java | 29 ++ .../IndicesSiteSearchMetricType.java | 68 +++++ .../TotalSizeSiteSearchIndicesMetricType.java | 33 ++ ...alAdvancedTemplatesDatabaseMetricType.java | 37 +++ ...talBuilderTemplatesDatabaseMetricType.java | 37 +++ .../TotalTemplatesDatabaseMetricType.java | 47 +++ ...emplatesInLivePagesDatabaseMetricType.java | 38 +++ ...latesInWorkingPagesDatabaseMetricType.java | 38 +++ .../theme/TotalFilesInThemeMetricType.java | 41 +++ .../TotalLiveContainerDatabaseMetricType.java | 42 +++ .../TotalLiveFilesInThemeMetricType.java | 41 +++ .../theme/TotalThemeMetricType.java | 38 +++ ...talThemeUsedInLiveTemplatesMetricType.java | 38 +++ ...ThemeUsedInWorkingTemplatesMetricType.java | 38 +++ ...talWorkingContainerDatabaseMetricType.java | 42 +++ ...tentTypesWithUrlMapDatabaseMetricType.java | 36 +++ ...LiveContentInUrlMapDatabaseMetricType.java | 40 +++ ...terWithTwoVariablesDatabaseMetricType.java | 37 +++ ...kingContentInUrlMapDatabaseMetricType.java | 40 +++ .../user/ActiveUsersDatabaseMetricType.java | 36 +++ .../user/LastLoginDatabaseMetricType.java | 36 +++ .../user/LastLoginUserDatabaseMetric.java | 36 +++ .../user/UsersDatabaseMetricType.java | 15 + .../workflow/ActionsDatabaseMetricType.java | 37 +++ .../ContentTypesDatabaseMetricType.java | 38 +++ .../workflow/SchemesDatabaseMetricType.java | 36 +++ .../workflow/StepsDatabaseMetricType.java | 37 +++ .../SubActionsDatabaseMetricType.java | 41 +++ .../UniqueSubActionsDatabaseMetricType.java | 41 +++ .../dotcms/telemetry/job/MetricsStatsJob.java | 48 +++ .../com/dotcms/telemetry/osgi/Activator.java | 111 +++++++ .../telemetry/osgi/PluginVersionUtil.java | 18 ++ .../ResponseEntityMetricsSnapshotView.java | 14 + .../telemetry/rest/TelemetryResource.java | 51 ++++ .../telemetry/util/IndicesSiteSearchUtil.java | 30 ++ .../com/dotcms/telemetry/util/JsonUtil.java | 24 ++ .../dotcms/telemetry/util/MetricCache.java | 33 ++ .../dotcms/telemetry/util/MetricCaches.java | 33 ++ 124 files changed, 5852 insertions(+) create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/Metric.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricCalculationError.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricCategory.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricFeature.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricValue.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/MetricsSnapshot.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/business/MetricEndpointPayload.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/business/MetricFactory.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/business/MetricsAPI.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/DBMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/MetricStatsCollector.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricAPI.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactory.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactorySubmitter.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricRequest.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricTypes.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricWebInterceptor.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/RequestHashCalculator.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLivePageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLiveTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInTemplateDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInWorkingPageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLivePageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLiveTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInWorkingPageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLivePageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLiveTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInWorkingPageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LastContentEditedDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LiveNotDefaultLanguageContentsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/RecentlyEditedContentDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/TotalContentsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/WorkingNotDefaultLanguageContentsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/ContentTypeFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBinaryFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBlockEditorFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCategoryFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCheckboxFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfColumnsFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfConstantFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateTimeFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfFileFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfHiddenFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfImageFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfJSONFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfKeyValueFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfLineDividersFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfMultiselectFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfPermissionsFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRadioFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRelationshipFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRowsFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSelectFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSiteOrFolderFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTabFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTagFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextAreaFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTimeFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfWYSIWYGFieldsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageBEAPICalls.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageFEAPICalls.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageBEAPICalls.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageFEAPICalls.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/HasChangeDefaultLanguagesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/OldStyleLanguagesVarialeMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLanguagesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLiveLanguagesVariablesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalUniqueLanguagesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalWorkingLanguagesVariablesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfLiveSitesWithSiteVariablesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithIndividualPermissionsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithSiteVariablesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithThumbnailsMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfWorkingSitesWithSiteVariablesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoDefaultTagStorageDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoSystemFieldsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithRunDashboardDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalActiveSitesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesActiveSitesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesAllSitesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalSitesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchDocumentMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchIndicesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/IndicesSiteSearchMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/TotalSizeSiteSearchIndicesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalAdvancedTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalBuilderTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInLivePagesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInWorkingPagesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalFilesInThemeMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveContainerDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveFilesInThemeMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInLiveTemplatesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInWorkingTemplatesMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalWorkingContainerDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/ContentTypesWithUrlMapDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/LiveContentInUrlMapDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/UrlMapPatterWithTwoVariablesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/WorkingContentInUrlMapDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/ActiveUsersDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginUserDatabaseMetric.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/UsersDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ActionsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ContentTypesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SchemesDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/StepsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SubActionsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/UniqueSubActionsDatabaseMetricType.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/job/MetricsStatsJob.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/osgi/Activator.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/osgi/PluginVersionUtil.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/rest/ResponseEntityMetricsSnapshotView.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/rest/TelemetryResource.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/util/IndicesSiteSearchUtil.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/util/JsonUtil.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCache.java create mode 100644 dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCaches.java diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/Metric.java b/dotCMS/src/main/java/com/dotcms/telemetry/Metric.java new file mode 100644 index 000000000000..915c6ae20d06 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/Metric.java @@ -0,0 +1,83 @@ +package com.dotcms.telemetry; + +/** + * Represents all the information needed to identify a Metric: + *
    + *
  • Name
  • + *
  • Description
  • + *
  • Category
  • + *
  • Feature
  • + *
+ */ +public class Metric { + + private final String name; + private final String description; + private final MetricCategory category; + private final MetricFeature feature; + + public Metric(final Builder builder) { + this.name = builder.name; + this.description = builder.description; + this.category = builder.category; + this.feature = builder.feature; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public MetricCategory getCategory() { + return category; + } + + public MetricFeature getFeature() { + return feature; + } + + @Override + public String toString() { + return "Metric{" + + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", category=" + category + + ", feature=" + feature + + '}'; + } + + public static class Builder { + String name; + String description; + MetricCategory category; + MetricFeature feature; + + public Builder name(final String name) { + this.name = name; + return this; + } + + public Builder description(final String description) { + this.description = description; + return this; + } + + public Builder category(final MetricCategory category) { + this.category = category; + return this; + } + + public Builder feature(final MetricFeature feature) { + this.feature = feature; + return this; + } + + public Metric build() { + return new Metric(this); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricCalculationError.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricCalculationError.java new file mode 100644 index 000000000000..bb734d785d96 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricCalculationError.java @@ -0,0 +1,35 @@ +package com.dotcms.telemetry; + +import com.fasterxml.jackson.annotation.JsonUnwrapped; + +/** + * Represent an error that occurs while calculating the metric. + */ +public class MetricCalculationError { + + @JsonUnwrapped + private final Metric metric; + private final String error; + + public MetricCalculationError(Metric metric, String error) { + this.metric = metric; + this.error = error; + } + + public Metric getType() { + return metric; + } + + public String getError() { + return error; + } + + @Override + public String toString() { + return "MetricCalculationError{" + + "metric=" + metric + + ", error='" + error + '\'' + + '}'; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricCategory.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricCategory.java new file mode 100644 index 000000000000..f26a43d7712e --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricCategory.java @@ -0,0 +1,27 @@ +package com.dotcms.telemetry; + +/** + * Represents the Metric Category where the {@link MetricType} belongs to + */ +public enum MetricCategory { + + DIFFERENTIATING_FEATURES("Differentiating Features"), + PAID_FEATURES("Paid Features"), + PLATFORM_SPECIFIC_CUSTOMIZATION("Platform-Specific Customization"), + SOPHISTICATED_CONTENT_ARCHITECTURE("Sophisticated Content Architecture"), + POSITIVE_USER_EXPERIENCE("Positive User Experience (incl. content velocity)"), + PLATFORM_SPECIFIC_DEVELOPMENT("Platform-Specific Development"), + RECENT_ACTIVITY("Recent Activity"), + HISTORY_LEGACY_DEPRECATED_FEATURES("History (incl. legacy/deprecated features"); + + private final String label; + + MetricCategory(final String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricFeature.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricFeature.java new file mode 100644 index 000000000000..77a01b5c0e31 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricFeature.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry; + +/** + * Represents the dotCMS feature that the {@link MetricType} belongs to + */ +public enum MetricFeature { + + CONTENTLETS, + LANGUAGES, + CONTENT_TYPES, + SITES, + URL_MAPS, + WORKFLOW, + USERS, + SITE_SEARCH, + IMAGE_API, + LAYOUT, + CONTENT_TYPE_FIELDS + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricType.java new file mode 100644 index 000000000000..9d1d3d121c77 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricType.java @@ -0,0 +1,59 @@ +package com.dotcms.telemetry; + +import com.dotmarketing.exception.DotDataException; + +import java.util.Optional; + +/** + * This interface represents a Metric that needs to be calculated and included in a MetricSnapshot. + * For each of these a new concrete class implements this interface must be created. The interface + * provides a set of methods to define the metadata for the Metric, such as its name, description, + * category, and feature. It also includes a method to calculate the Metric's value. + *
    + *
  • Metadata Methods: The getName, getDescription, getCategory, and getFeature methods can + * be overridden to set the metadata for a specific Metric. The getMetric method creates a + * Metric object using the values returned by these methods. The Metric class represents the + * metadata of a single Metric.
  • + *
  • Value Calculation Method: You can override the getValue method to define how the + * Metric value is calculated. This method returns an object, so the value can be of any type. + * To perform this calculation, you can use SQL queries, dotCMS API methods, Java core code, or + * any other approach that suits your needs.
  • + *
+ *

Some of the Metrics to collect are:

+ *
    + *
  • Count of workflow schemes
  • + *
  • Count of Site Search indexes
  • + *
  • Count of sites
  • + *
  • Count of content types with URL maps
  • + *
  • etc
  • + *
+ * + * @see MetricCategory + * @see MetricFeature + */ +public interface MetricType { + + String getName(); + + String getDescription(); + + MetricCategory getCategory(); + + MetricFeature getFeature(); + + Optional getValue(); + + default Metric getMetric() { + return new Metric.Builder() + .name(getName()) + .description(getDescription()) + .category(getCategory()) + .feature(getFeature()) + .build(); + } + + default Optional getStat() throws DotDataException { + return getValue().map(o -> new MetricValue(this.getMetric(), o)); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricValue.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricValue.java new file mode 100644 index 000000000000..2e59fbde726b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricValue.java @@ -0,0 +1,62 @@ +package com.dotcms.telemetry; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import org.apache.commons.lang.math.NumberUtils; + +import java.text.DecimalFormat; + +/** + * Represents the value for a {@link MetricType} + */ +public class MetricValue { + + private static final DecimalFormat FORMAT = new DecimalFormat("0.##"); + + @JsonUnwrapped + final Metric metric; + + final Object value; + + public MetricValue(final Metric metric, final Object value) { + this.metric = metric; + this.value = value; + } + + /** + * Check if the value of the Metric is a numeric value. + * + * @return true if the value is a numeric value + */ + @JsonIgnore + public boolean isNumeric() { + return NumberUtils.isNumber(value.toString()); + } + + public Metric getMetric() { + return metric; + } + + /** + * Return the value of the Metric if it is a numeric value then return it as a String formatted + * with two decimals + * + * @return + */ + public Object getValue() { + if (isNumeric()) { + return FORMAT.format(Double.parseDouble(value.toString())); + } else { + return value; + } + } + + @Override + public String toString() { + return "MetricValue{" + + "metric=" + metric + + ", value=" + value + + '}'; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/MetricsSnapshot.java b/dotCMS/src/main/java/com/dotcms/telemetry/MetricsSnapshot.java new file mode 100644 index 000000000000..d0e5ab566690 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/MetricsSnapshot.java @@ -0,0 +1,93 @@ +package com.dotcms.telemetry; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Represents a snapshot of metric statistics, including all calculated metrics, separated into + * numeric and non-numeric categories. It also contains a list of errors, indicating any metrics + * that encountered exceptions during calculation. + */ +public class MetricsSnapshot { + + /** + * Collection of Numeric Metrics + */ + final Collection stats; + + /** + * Collection of No Numeric Metrics + */ + final Collection notNumericStats; + + /** + * Metric that thrown an Exception during the calculation process + */ + final Collection errors; + + public MetricsSnapshot(final Builder builder) { + this.stats = builder.stats; + this.notNumericStats = builder.notNumericStats; + this.errors = builder.errors; + } + + @JsonProperty + public Collection getStats() { + return stats; + } + + @JsonProperty + public Collection getErrors() { + return errors; + } + + @JsonAnyGetter + public Map getNotNumericStats() { + final Map result = new HashMap<>(); + + for (final MetricValue stat : notNumericStats) { + result.put(stat.getMetric().getName(), stat.getValue().toString()); + } + + return result; + } + + @Override + public String toString() { + return "MetricsSnapshot{" + + "stats=" + stats + + ", notNumericStats=" + notNumericStats + + ", errors=" + errors + + '}'; + } + + public static class Builder { + private Collection stats; + private Collection notNumericStats; + private Collection errors; + + public Builder stats(Collection stats) { + this.stats = stats; + return this; + } + + public Builder notNumericStats(Collection notNumericStats) { + this.notNumericStats = notNumericStats; + return this; + } + + public Builder errors(Collection errors) { + this.errors = errors; + return this; + } + + public MetricsSnapshot build() { + return new MetricsSnapshot(this); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricEndpointPayload.java b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricEndpointPayload.java new file mode 100644 index 000000000000..2549f7fb88ed --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricEndpointPayload.java @@ -0,0 +1,125 @@ +package com.dotcms.telemetry.business; + +import com.dotcms.telemetry.MetricsSnapshot; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +/** + * Payload to be sent to the Metric Endpoint + */ +public class MetricEndpointPayload { + + static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm" + + ":ss.S'Z'") + .withZone(ZoneId.systemDefault()); + private final String clientName; + private final String clientEnv; + private final int clientVersion; + private final String clientCategory; + private final long schemaVersion; + private final String insertDate; + private final MetricsSnapshot snapshot; + + private MetricEndpointPayload(final Builder builder) { + this.clientName = builder.clientName; + this.clientEnv = builder.clientEnv; + this.clientVersion = builder.clientVersion; + this.clientCategory = builder.clientCategory; + this.schemaVersion = builder.schemaVersion; + this.insertDate = DATE_FORMAT.format(builder.insertDate); + this.snapshot = builder.snapshot; + } + + public String getClientName() { + return clientName; + } + + public String getClientEnv() { + return clientEnv; + } + + public int getClientVersion() { + return clientVersion; + } + + public String getClientCategory() { + return clientCategory; + } + + public long getSchemaVersion() { + return schemaVersion; + } + + public String getInsertDate() { + return insertDate; + } + + public MetricsSnapshot getSnapshot() { + return snapshot; + } + + @Override + public String toString() { + return "MetricEndpointPayload{" + + "clientName='" + clientName + '\'' + + ", clientEnv='" + clientEnv + '\'' + + ", clientVersion=" + clientVersion + + ", clientCategory='" + clientCategory + '\'' + + ", schemaVersion=" + schemaVersion + + ", insertDate='" + insertDate + '\'' + + ", snapshot=" + snapshot + + '}'; + } + + public static class Builder { + private String clientName; + private String clientEnv; + private int clientVersion; + private String clientCategory; + private long schemaVersion; + private Instant insertDate; + private MetricsSnapshot snapshot; + + public Builder clientName(String clientName) { + this.clientName = clientName; + return this; + } + + public Builder clientEnv(String clientEnv) { + this.clientEnv = clientEnv; + return this; + } + + public Builder clientVersion(int version) { + this.clientVersion = version; + return this; + } + + public Builder clientCategory(String clientCategory) { + this.clientCategory = clientCategory; + return this; + } + + public Builder schemaVersion(long schemaVersion) { + this.schemaVersion = schemaVersion; + return this; + } + + public Builder insertDate(Instant insertDate) { + this.insertDate = insertDate; + return this; + } + + public Builder snapshot(MetricsSnapshot snapshot) { + this.snapshot = snapshot; + return this; + } + + public MetricEndpointPayload build() { + return new MetricEndpointPayload(this); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricFactory.java b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricFactory.java new file mode 100644 index 000000000000..0c3ef97a621a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricFactory.java @@ -0,0 +1,77 @@ +package com.dotcms.telemetry.business; + +import com.dotcms.business.CloseDBIfOpened; +import com.dotmarketing.common.db.DotConnect; +import com.dotmarketing.db.DbConnectionFactory; +import com.dotmarketing.exception.DotDataException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Utility class tha provide methods to run SQL Query into dotCMS DataBase + */ +public enum MetricFactory { + + INSTANCE; + + @CloseDBIfOpened + public Optional getValue(final String sqlQuery) throws DotDataException { + final DotConnect dotConnect = new DotConnect(); + final List> loadObjectResults = dotConnect.setSQL(sqlQuery) + .loadObjectResults(); + + if (loadObjectResults.isEmpty()) { + return Optional.empty(); + } + + return Optional.ofNullable(loadObjectResults.get(0).get("value")); + } + + /** + * Execute a query that returns a list of String objects. The query should retrieve a field + * called value, as shown in the example below: + *
+     * {@code
+     * SELECT identifier as value FROM template
+     * }
+     * 
+ *

+ * This method will iterate through the results returned by the query and use the values from + * the value field to create a Collection of Strings. + * + * @param sqlQuery the query to be executed. + * + * @return a Collection of Strings with the values returned by the query. + * + * @throws DotDataException if an error occurs while executing the query. + */ + @CloseDBIfOpened + public Optional> getList(final String sqlQuery) throws DotDataException { + final DotConnect dotConnect = new DotConnect(); + final List> loadObjectResults = dotConnect.setSQL(sqlQuery) + .loadObjectResults(); + + if (loadObjectResults.isEmpty()) { + return Optional.empty(); + } + + return Optional.of( + loadObjectResults.stream().map(item -> item.get("value").toString()).collect(Collectors.toList()) + ); + } + + @CloseDBIfOpened + @SuppressWarnings("unchecked") + public int getSchemaDBVersion() throws DotDataException { + final ArrayList> results = new DotConnect() + .setSQL("SELECT max(db_version) AS version FROM db_version") + .loadResults(); + + return Integer.parseInt(results.get(0).get("version").toString()); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricsAPI.java b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricsAPI.java new file mode 100644 index 000000000000..f5d46f953f45 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/business/MetricsAPI.java @@ -0,0 +1,259 @@ +package com.dotcms.telemetry.business; + +import com.dotcms.telemetry.MetricsSnapshot; +import com.dotcms.telemetry.util.JsonUtil; +import com.dotcms.http.CircuitBreakerUrl; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.db.LocalTransaction; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotRuntimeException; +import com.dotmarketing.util.Config; +import com.dotmarketing.util.Logger; + +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * API for all the Metrics related operations + */ +public enum MetricsAPI { + + INSTANCE; + + final String endPointUrl = Config.getStringProperty("TELEMETRY_PERSISTENCE_ENDPOINT", + "https://dotcms-prod-1.analytics.dotcms.cloud/m"); + + final String customCategory = Config.getStringProperty("TELEMETRY_CLIENT_CATEGORY", + null); + + final String clientNameFromConfig = Config.getStringProperty("TELEMETRY_CLIENT_NAME", + null); + + final int clientEnvVersionFromConfig = Config.getIntProperty("TELEMETRY_CLIENT_VERSION", + -1); + + final String clientEnvFromConfig = Config.getStringProperty("TELEMETRY_CLIENT_ENV", + null); + + final int maxAttemptsToFail = Config.getIntProperty("TELEMETRY_MAX_ATTEMPTS_TO_FAIL", 3); + final int tryAgainDelay = Config.getIntProperty("TELEMETRY_TRY_AGAIN_DELAY", 30); + final int requestTimeout = Config.getIntProperty("TELEMETRY_REQUEST_TIMEOUT", 4000); + + private static int getSchemaDBVersion() throws DotDataException { + try { + return LocalTransaction.wrapReturn(MetricFactory.INSTANCE::getSchemaDBVersion); + } catch (DotDataException e) { + throw e; + } catch (Exception e) { + throw new DotRuntimeException(e); + } + + } + + /** + * Persists the given {@link MetricsSnapshot} + * + * @param metricsSnapshot the snapshot to persist + */ + public void persistMetricsSnapshot(final MetricsSnapshot metricsSnapshot) throws DotDataException { + Logger.debug(this, "Persisting the snapshot"); + + final Client client = getClient(); + + sendMetric(new MetricEndpointPayload.Builder() + .clientName(client.getClientName()) + .clientEnv(client.getEnvironment()) + .clientVersion(client.getVersion()) + .clientCategory(client.getCategory()) + .schemaVersion(getSchemaDBVersion()) + .insertDate(Instant.now()) + .snapshot(metricsSnapshot) + .build() + ); + } + + /** + * Use the {@link MetricFactory#getList(String)} method to execute a Query and return a + * Collection of String + * + * @param sqlQuery the query to be executed + * + * @return a Collection of Strings with the values returned by the query + * + * @see MetricFactory#getList(String) + */ + public List getList(final String sqlQuery) { + try { + return LocalTransaction.wrapReturn(() -> MetricFactory.INSTANCE.getList(sqlQuery)) + .orElse(Collections.emptyList()); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + public Optional getValue(final String sqlQuery) { + try { + return LocalTransaction.wrapReturn(() -> MetricFactory.INSTANCE.getValue(sqlQuery)); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + public Client getClient() throws DotDataException { + + Client client = getClientMetaDataFromHostName(); + + return new Client.Builder() + .clientName(clientNameFromConfig != null ? clientNameFromConfig : + client.getClientName()) + .category(customCategory != null ? customCategory : client.getCategory()) + .version(clientEnvVersionFromConfig != -1 ? clientEnvVersionFromConfig : + client.getVersion()) + .environment(clientEnvFromConfig != null ? clientEnvFromConfig : + client.getEnvironment()) + .build(); + } + + private Client getClientMetaDataFromHostName() throws DotDataException { + final String hostname = APILocator.getServerAPI().getCurrentServer().getName(); + final String[] split = hostname.split("-"); + + final Client.Builder builder = new Client.Builder(); + + if (split.length < 4) { + builder.clientName(hostname) + .environment(hostname) + .version(0); + } else { + final String clientName = String.join("-", Arrays.copyOfRange(split, 1, + split.length - 2)); + + builder.clientName(clientName) + .environment(split[split.length - 2]) + .version(Integer.parseInt(split[split.length - 1])); + + } + + getCategoryFromHostName(hostname).map(ClientCategory::name).ifPresent(builder::category); + + return builder.build(); + } + + private Optional getCategoryFromHostName(final String hostname) { + if (hostname.startsWith("dotcms-corpsites")) { + return Optional.of(ClientCategory.DOTCMS); + } else if (hostname.startsWith("dotcms-")) { + return Optional.of(ClientCategory.CLIENT); + } + + return Optional.empty(); + } + + + private void sendMetric(final MetricEndpointPayload metricEndpointPayload) { + + final CircuitBreakerUrl circuitBreakerUrl = CircuitBreakerUrl.builder() + .setMethod(CircuitBreakerUrl.Method.POST) + .setUrl(endPointUrl) + .setHeaders(Map.of("Content-Type", "application/json")) + .setRawData(JsonUtil.INSTANCE.getAsJson(metricEndpointPayload)) + .setFailAfter(maxAttemptsToFail) + .setTryAgainAfterDelaySeconds(tryAgainDelay) + .setTimeout(requestTimeout) + .build(); + + try { + circuitBreakerUrl.doString(); + final int response = circuitBreakerUrl.response(); + if (response != 201) { + Logger.debug(this, + "ERROR: Unable to save the Metric. HTTP error code: " + response); + } + } catch (Exception e) { + Logger.debug(this, "ERROR: Unable to save the Metric."); + } + } + + private enum ClientCategory { + DOTCMS, + CLIENT + } + + public static class Client { + final String clientName; + final String environment; + final int version; + + final String category; + + public Client(final Builder builder) { + this.clientName = builder.clientName; + this.environment = builder.environment; + this.version = builder.version; + this.category = builder.category; + } + + @Override + public String toString() { + return "Client{" + + "clientName='" + clientName + '\'' + + ", environment='" + environment + '\'' + + ", version=" + version + + ", category='" + category + '\'' + + '}'; + } + + public String getClientName() { + return clientName; + } + + public String getEnvironment() { + return environment; + } + + public int getVersion() { + return version; + } + + public String getCategory() { + return category; + } + + public static class Builder { + String clientName; + String environment; + int version; + + String category; + + Builder clientName(final String clientName) { + this.clientName = clientName; + return this; + } + + Builder environment(final String environment) { + this.environment = environment; + return this; + } + + Builder version(final int version) { + this.version = version; + return this; + } + + Builder category(final String category) { + this.category = category; + return this; + } + + Client build() { + return new Client(this); + } + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/DBMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/DBMetricType.java new file mode 100644 index 000000000000..24f3b45c61c6 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/DBMetricType.java @@ -0,0 +1,30 @@ +package com.dotcms.telemetry.collectors; + +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.MetricValue; +import com.dotcms.telemetry.business.MetricsAPI; + +import java.util.Optional; + +/** + * Represents the MetaData of a Metric that we want to collect from DataBase + * + * @see MetricType + */ +public interface DBMetricType extends MetricType { + + String getSqlQuery(); + + @Override + default Optional getValue() { + return MetricsAPI.INSTANCE.getValue(getSqlQuery()); + } + + @Override + default Optional getStat() { + return getValue() + .map(value -> new MetricValue(this.getMetric(), value)); + + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/MetricStatsCollector.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/MetricStatsCollector.java new file mode 100644 index 000000000000..8bdf3347cb70 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/MetricStatsCollector.java @@ -0,0 +1,289 @@ +package com.dotcms.telemetry.collectors; + +import com.dotcms.telemetry.MetricCalculationError; +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.MetricValue; +import com.dotcms.telemetry.MetricsSnapshot; +import com.dotcms.telemetry.collectors.api.ApiMetricAPI; +import com.dotcms.telemetry.collectors.api.ApiMetricTypes; +import com.dotcms.telemetry.collectors.container.TotalFileContainersInLivePageDatabaseMetricType; +import com.dotcms.telemetry.collectors.container.TotalFileContainersInLiveTemplatesDatabaseMetricType; +import com.dotcms.telemetry.collectors.container.TotalFileContainersInWorkingPageDatabaseMetricType; +import com.dotcms.telemetry.collectors.container.TotalStandardContainersInLivePageDatabaseMetricType; +import com.dotcms.telemetry.collectors.container.TotalStandardContainersInLiveTemplatesDatabaseMetricType; +import com.dotcms.telemetry.collectors.container.TotalStandardContainersInWorkingPageDatabaseMetricType; +import com.dotcms.telemetry.collectors.content.LastContentEditedDatabaseMetricType; +import com.dotcms.telemetry.collectors.content.LiveNotDefaultLanguageContentsDatabaseMetricType; +import com.dotcms.telemetry.collectors.content.RecentlyEditedContentDatabaseMetricType; +import com.dotcms.telemetry.collectors.content.TotalContentsDatabaseMetricType; +import com.dotcms.telemetry.collectors.content.WorkingNotDefaultLanguageContentsDatabaseMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfCategoryFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfConstantFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfDateFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfDateTimeFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfHiddenFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfPermissionsFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfRelationshipFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfSiteOrFolderFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfTagFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfTextAreaFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfTextFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfTimeFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfWYSIWYGFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfBinaryFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfBlockEditorFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfCheckboxFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfColumnsFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfFileFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfImageFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfJSONFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfKeyValueFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfLineDividersFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfMultiselectFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfRadioFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfRowsFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfSelectFieldsMetricType; +import com.dotcms.telemetry.collectors.contenttype.CountOfTabFieldsMetricType; +import com.dotcms.telemetry.collectors.language.HasChangeDefaultLanguagesDatabaseMetricType; +import com.dotcms.telemetry.collectors.language.OldStyleLanguagesVarialeMetricType; +import com.dotcms.telemetry.collectors.language.TotalLanguagesDatabaseMetricType; +import com.dotcms.telemetry.collectors.language.TotalLiveLanguagesVariablesDatabaseMetricType; +import com.dotcms.telemetry.collectors.language.TotalUniqueLanguagesDatabaseMetricType; +import com.dotcms.telemetry.collectors.language.TotalWorkingLanguagesVariablesDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.CountOfLiveSitesWithSiteVariablesMetricType; +import com.dotcms.telemetry.collectors.site.CountOfSitesWithIndividualPermissionsMetricType; +import com.dotcms.telemetry.collectors.site.CountOfSitesWithThumbnailsMetricType; +import com.dotcms.telemetry.collectors.site.CountOfWorkingSitesWithSiteVariablesMetricType; +import com.dotcms.telemetry.collectors.site.SitesWithNoDefaultTagStorageDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.SitesWithNoSystemFieldsDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.SitesWithRunDashboardDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.TotalActiveSitesDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.TotalAliasesActiveSitesDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.TotalAliasesAllSitesDatabaseMetricType; +import com.dotcms.telemetry.collectors.site.TotalSitesDatabaseMetricType; +import com.dotcms.telemetry.collectors.sitesearch.CountSiteSearchDocumentMetricType; +import com.dotcms.telemetry.collectors.sitesearch.CountSiteSearchIndicesMetricType; +import com.dotcms.telemetry.collectors.sitesearch.TotalSizeSiteSearchIndicesMetricType; +import com.dotcms.telemetry.collectors.template.TotalAdvancedTemplatesDatabaseMetricType; +import com.dotcms.telemetry.collectors.template.TotalBuilderTemplatesDatabaseMetricType; +import com.dotcms.telemetry.collectors.template.TotalTemplatesDatabaseMetricType; +import com.dotcms.telemetry.collectors.template.TotalTemplatesInLivePagesDatabaseMetricType; +import com.dotcms.telemetry.collectors.template.TotalTemplatesInWorkingPagesDatabaseMetricType; +import com.dotcms.telemetry.collectors.theme.TotalFilesInThemeMetricType; +import com.dotcms.telemetry.collectors.theme.TotalLiveContainerDatabaseMetricType; +import com.dotcms.telemetry.collectors.theme.TotalLiveFilesInThemeMetricType; +import com.dotcms.telemetry.collectors.theme.TotalThemeMetricType; +import com.dotcms.telemetry.collectors.theme.TotalThemeUsedInLiveTemplatesMetricType; +import com.dotcms.telemetry.collectors.theme.TotalThemeUsedInWorkingTemplatesMetricType; +import com.dotcms.telemetry.collectors.theme.TotalWorkingContainerDatabaseMetricType; +import com.dotcms.telemetry.collectors.urlmap.ContentTypesWithUrlMapDatabaseMetricType; +import com.dotcms.telemetry.collectors.urlmap.LiveContentInUrlMapDatabaseMetricType; +import com.dotcms.telemetry.collectors.urlmap.UrlMapPatterWithTwoVariablesDatabaseMetricType; +import com.dotcms.telemetry.collectors.urlmap.WorkingContentInUrlMapDatabaseMetricType; +import com.dotcms.telemetry.collectors.user.ActiveUsersDatabaseMetricType; +import com.dotcms.telemetry.collectors.user.LastLoginDatabaseMetricType; +import com.dotcms.telemetry.collectors.user.LastLoginUserDatabaseMetric; +import com.dotcms.telemetry.collectors.workflow.ActionsDatabaseMetricType; +import com.dotcms.telemetry.collectors.workflow.ContentTypesDatabaseMetricType; +import com.dotcms.telemetry.collectors.workflow.SchemesDatabaseMetricType; +import com.dotcms.telemetry.collectors.workflow.StepsDatabaseMetricType; +import com.dotcms.telemetry.collectors.workflow.SubActionsDatabaseMetricType; +import com.dotcms.telemetry.collectors.workflow.UniqueSubActionsDatabaseMetricType; +import com.dotcms.telemetry.util.MetricCaches; +import com.dotmarketing.db.DbConnectionFactory; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.util.Logger; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; + +/** + * This class collects and generates all the different Metrics that will be reported to a User or + * any other application/client. + * + * @author Freddy Rodriguez + * @since Jan 8th, 2024 + */ +public final class MetricStatsCollector { + + public static final ApiMetricAPI apiStatAPI = new ApiMetricAPI(); + static final Collection metricStatsCollectors; + + private MetricStatsCollector() { + + } + + static { + metricStatsCollectors = new HashSet<>(); + + metricStatsCollectors.add(new LastContentEditedDatabaseMetricType()); + metricStatsCollectors.add(new RecentlyEditedContentDatabaseMetricType()); + metricStatsCollectors.add(new LastLoginDatabaseMetricType()); + metricStatsCollectors.add(new LastLoginUserDatabaseMetric()); + + metricStatsCollectors.add(new SchemesDatabaseMetricType()); + metricStatsCollectors.add(new ContentTypesDatabaseMetricType()); + metricStatsCollectors.add(new StepsDatabaseMetricType()); + metricStatsCollectors.add(new ActionsDatabaseMetricType()); + metricStatsCollectors.add(new SubActionsDatabaseMetricType()); + metricStatsCollectors.add(new UniqueSubActionsDatabaseMetricType()); + + metricStatsCollectors.add(new TotalContentsDatabaseMetricType()); + metricStatsCollectors.add(new WorkingNotDefaultLanguageContentsDatabaseMetricType()); + metricStatsCollectors.add(new LiveNotDefaultLanguageContentsDatabaseMetricType()); + metricStatsCollectors.add(new OldStyleLanguagesVarialeMetricType()); + + metricStatsCollectors.add(new ActiveUsersDatabaseMetricType()); + metricStatsCollectors.add(new ContentTypesWithUrlMapDatabaseMetricType()); + metricStatsCollectors.add(new LiveContentInUrlMapDatabaseMetricType()); + metricStatsCollectors.add(new UrlMapPatterWithTwoVariablesDatabaseMetricType()); + metricStatsCollectors.add(new WorkingContentInUrlMapDatabaseMetricType()); + + metricStatsCollectors.add(new HasChangeDefaultLanguagesDatabaseMetricType()); + metricStatsCollectors.add(new TotalLanguagesDatabaseMetricType()); + metricStatsCollectors.add(new TotalLiveLanguagesVariablesDatabaseMetricType()); + metricStatsCollectors.add(new TotalUniqueLanguagesDatabaseMetricType()); + metricStatsCollectors.add(new TotalWorkingLanguagesVariablesDatabaseMetricType()); + + metricStatsCollectors.add(new CountOfSitesWithIndividualPermissionsMetricType()); + metricStatsCollectors.add(new CountOfSitesWithThumbnailsMetricType()); + metricStatsCollectors.add(new CountOfWorkingSitesWithSiteVariablesMetricType()); + metricStatsCollectors.add(new CountOfLiveSitesWithSiteVariablesMetricType()); + + metricStatsCollectors.add(new SitesWithNoSystemFieldsDatabaseMetricType()); + metricStatsCollectors.add(new SitesWithNoDefaultTagStorageDatabaseMetricType()); + metricStatsCollectors.add(new SitesWithRunDashboardDatabaseMetricType()); + metricStatsCollectors.add(new TotalAliasesAllSitesDatabaseMetricType()); + metricStatsCollectors.add(new TotalAliasesActiveSitesDatabaseMetricType()); + metricStatsCollectors.add(new TotalSitesDatabaseMetricType()); + metricStatsCollectors.add(new TotalActiveSitesDatabaseMetricType()); + metricStatsCollectors.add(new TotalAdvancedTemplatesDatabaseMetricType()); + + metricStatsCollectors.add(new CountSiteSearchDocumentMetricType()); + metricStatsCollectors.add(new CountSiteSearchIndicesMetricType()); + metricStatsCollectors.add(new TotalSizeSiteSearchIndicesMetricType()); + + metricStatsCollectors.add(new TotalTemplatesDatabaseMetricType()); + metricStatsCollectors.add(new TotalTemplatesInLivePagesDatabaseMetricType()); + metricStatsCollectors.add(new TotalTemplatesInWorkingPagesDatabaseMetricType()); + metricStatsCollectors.add(new TotalBuilderTemplatesDatabaseMetricType()); + + metricStatsCollectors.add(new TotalThemeUsedInLiveTemplatesMetricType()); + metricStatsCollectors.add(new TotalThemeUsedInWorkingTemplatesMetricType()); + + metricStatsCollectors.add(new TotalLiveFilesInThemeMetricType()); + metricStatsCollectors.add(new TotalFilesInThemeMetricType()); + metricStatsCollectors.add(new TotalThemeMetricType()); + + metricStatsCollectors.add(new TotalLiveContainerDatabaseMetricType()); + metricStatsCollectors.add(new TotalWorkingContainerDatabaseMetricType()); + + metricStatsCollectors.add(new TotalStandardContainersInLivePageDatabaseMetricType()); + metricStatsCollectors.add(new TotalFileContainersInLivePageDatabaseMetricType()); + metricStatsCollectors.add(new TotalStandardContainersInWorkingPageDatabaseMetricType()); + metricStatsCollectors.add(new TotalFileContainersInWorkingPageDatabaseMetricType()); + + metricStatsCollectors.add(new TotalFileContainersInLiveTemplatesDatabaseMetricType()); + metricStatsCollectors.add(new TotalStandardContainersInLiveTemplatesDatabaseMetricType()); + + metricStatsCollectors.add(new CountOfCategoryFieldsMetricType()); + metricStatsCollectors.add(new CountOfConstantFieldsMetricType()); + metricStatsCollectors.add(new CountOfDateFieldsMetricType()); + metricStatsCollectors.add(new CountOfDateTimeFieldsMetricType()); + metricStatsCollectors.add(new CountOfBinaryFieldsMetricType()); + metricStatsCollectors.add(new CountOfBlockEditorFieldsMetricType()); + metricStatsCollectors.add(new CountOfCheckboxFieldsMetricType()); + metricStatsCollectors.add(new CountOfColumnsFieldsMetricType()); + metricStatsCollectors.add(new CountOfFileFieldsMetricType()); + metricStatsCollectors.add(new CountOfImageFieldsMetricType()); + metricStatsCollectors.add(new CountOfJSONFieldsMetricType()); + metricStatsCollectors.add(new CountOfKeyValueFieldsMetricType()); + metricStatsCollectors.add(new CountOfLineDividersFieldsMetricType()); + metricStatsCollectors.add(new CountOfMultiselectFieldsMetricType()); + metricStatsCollectors.add(new CountOfRadioFieldsMetricType()); + metricStatsCollectors.add(new CountOfRowsFieldsMetricType()); + metricStatsCollectors.add(new CountOfSelectFieldsMetricType()); + metricStatsCollectors.add(new CountOfTabFieldsMetricType()); + metricStatsCollectors.add(new CountOfHiddenFieldsMetricType()); + metricStatsCollectors.add(new CountOfPermissionsFieldsMetricType()); + metricStatsCollectors.add(new CountOfRelationshipFieldsMetricType()); + metricStatsCollectors.add(new CountOfSiteOrFolderFieldsMetricType()); + metricStatsCollectors.add(new CountOfTagFieldsMetricType()); + metricStatsCollectors.add(new CountOfTextAreaFieldsMetricType()); + metricStatsCollectors.add(new CountOfTextFieldsMetricType()); + metricStatsCollectors.add(new CountOfTimeFieldsMetricType()); + metricStatsCollectors.add(new CountOfWYSIWYGFieldsMetricType()); + + metricStatsCollectors.addAll(ApiMetricTypes.INSTANCE.get()); + } + + public static MetricsSnapshot getStatsAndCleanUp() { + final MetricsSnapshot stats = getStats(); + + apiStatAPI.flushTemporalTable(); + return stats; + } + + /** + * Calculate a MetricSnapshot by iterating through all the MetricType collections. + * + * @return the {@link MetricsSnapshot} with all the calculated metrics. + */ + public static MetricsSnapshot getStats() { + + final Collection stats = new ArrayList<>(); + final Collection noNumberStats = new ArrayList<>(); + Collection errors = new ArrayList<>(); + + try { + openDBConnection(); + + for (final MetricType metricType : metricStatsCollectors) { + try { + getMetricValue(metricType).ifPresent(metricValue -> { + if (metricValue.isNumeric()) { + stats.add(metricValue); + } else { + noNumberStats.add(metricValue); + } + }); + } catch (final Throwable e) { + errors.add(new MetricCalculationError(metricType.getMetric(), e.getMessage())); + Logger.debug(MetricStatsCollector.class, () -> + "Error while calculating Metric " + metricType.getName() + ": " + e.getMessage()); + } + } + } finally { + DbConnectionFactory.closeSilently(); + } + + MetricCaches.flushAll(); + + return new MetricsSnapshot.Builder() + .stats(stats) + .notNumericStats(noNumberStats) + .errors(errors) + .build(); + } + + private static Optional getMetricValue(final MetricType metricType) throws DotDataException { + final Optional metricStatsOptional = metricType.getStat(); + + if (metricStatsOptional.isPresent()) { + final MetricValue metricValue = metricStatsOptional.get(); + + if (metricValue.getValue() instanceof Boolean) { + return Optional.of(new MetricValue(metricValue.getMetric(), + Boolean.getBoolean(metricValue.getValue().toString()) ? 1 : 0)); + } + } + + return metricStatsOptional; + } + + private static void openDBConnection() { + DbConnectionFactory.getConnection(); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricAPI.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricAPI.java new file mode 100644 index 000000000000..a918f79373fc --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricAPI.java @@ -0,0 +1,107 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotmarketing.db.HibernateUtil; +import com.dotmarketing.db.LocalTransaction; +import com.dotmarketing.exception.DotRuntimeException; + +import java.time.Instant; +import java.util.Collection; +import java.util.Map; + +/** + * A utility class to interact with the metric_temporally_table table, providing methods to save or + * flush data. This class encapsulates the logic for saving and flushing data into the + * metric_temporally_table. + *

+ * The metric_temporally_table is a special table designed to store the request to the endpoints we + * wish to track. Later, the data in this table is summarized and stored as part of the + * MetricSnapshot. + */ +public class ApiMetricAPI { + + final RequestHashCalculator requestHashCalculator = new RequestHashCalculator(); + + /** + * Return all the summary from the temporal table + * + * @return Collection of Maps with the summary data. + * + * @see ApiMetricFactory + * @see ApiMetricAPI + */ + public static Collection> getMetricTemporaryTableData() { + try { + return ApiMetricFactory.INSTANCE.getMetricTemporaryTableData(); + } finally { + HibernateUtil.closeSessionSilently(); + } + } + + /** + * Save an Endpoint request to the metric_temporally_table. + *

+ * This is saved on an async way. + * + * @param apiMetricType Metric to be saved + * @param request Request data + */ + public void save(final ApiMetricType apiMetricType, + final ApiMetricWebInterceptor.RereadInputStreamRequest request) { + + final String requestHash = requestHashCalculator.calculate(apiMetricType, request); + final ApiMetricRequest metricAPIHit = new ApiMetricRequest.Builder() + .setMetric(apiMetricType.getMetric()) + .setTime(Instant.now()) + .setHash(requestHash) + .build(); + + ApiMetricFactorySubmitter.INSTANCE.saveAsync(metricAPIHit); + } + + /** + * Before beginning to collect endpoint requests, this function must be called. It saves a + * starting register to the metric_temporally_table, indicating the initiation of data + * collection + */ + public void startCollecting() { + try { + LocalTransaction.wrap(ApiMetricFactory.INSTANCE::saveStartEvent); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void flushTemporalTable() { + try { + LocalTransaction.wrap(() -> { + ApiMetricFactory.INSTANCE.flushTemporaryTable(); + startCollecting(); + }); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + /** + * Create the metrics_temp table + */ + public void createTemporaryTable() { + try { + LocalTransaction.wrap(ApiMetricFactory.INSTANCE::createTemporaryTable); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + /** + * Drop the metrics_temp table + */ + public void dropTemporaryTable() { + try { + LocalTransaction.wrap(ApiMetricFactory.INSTANCE::dropTemporaryTable); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactory.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactory.java new file mode 100644 index 000000000000..781c91de0972 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactory.java @@ -0,0 +1,180 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotcms.business.CloseDBIfOpened; +import com.dotmarketing.common.db.DotConnect; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotRuntimeException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.vavr.control.Try; +import org.postgresql.util.PGobject; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collection; +import java.util.Map; + +/** + * A utility class to interact with the metrics_temp table, providing the more basic methods to + * create/drop the table or save/flush data. + *

+ * This class encapsulates the queries for saving/flushing data into the metrics_temp and + * creating/dropping the whole table. + *

+ * The metrics_temp is a special table designed to store the request to the endpoints we wish to + * track. Later, the data in this table is summarized and stored as part of the MetricSnapshot. + */ +public enum ApiMetricFactory { + + INSTANCE; + + private static final String GET_DATA_FROM_TEMPORARY_METRIC_TABLE = + "SELECT " + + "metric_type->>'feature' as feature, " + + "metric_type->>'category' as category, " + + "metric_type->>'name' as name, " + + "COUNT(*) / %1$.2f AS average_per_hour, " + + "COUNT(distinct hash) / %1$.2f AS unique_average_per_hour " + + "FROM metrics_temp " + + "GROUP BY metric_type->>'feature', " + + "metric_type->>'category', " + + "metric_type->>'name' " + + "HAVING metric_type->>'name' IS NOT null"; + private static final String OVERALL_QUERY = "SELECT (EXTRACT(epoch FROM now()) - EXTRACT" + + "(epoch FROM MIN(timestamp)))/3600 " + + "as overall FROM metrics_temp"; + + final ObjectMapper jsonMapper = new ObjectMapper(); + + ApiMetricFactory() { + + } + + /** + * Save request on the metrics_temp + * + * @param apiMetricRequest request + */ + public void save(final ApiMetricRequest apiMetricRequest) { + try { + final String jsonStr = jsonMapper.writeValueAsString(apiMetricRequest.getMetric()); + + final PGobject jsonObject = new PGobject(); + jsonObject.setType("json"); + Try.run(() -> jsonObject.setValue(jsonStr)).getOrElseThrow( + () -> new IllegalArgumentException("Invalid JSON")); + + new DotConnect() + .setSQL("INSERT INTO metrics_temp (timestamp, metric_type, hash) VALUES (?, " + + "?, ?)") + .addParam(OffsetDateTime.now(ZoneOffset.UTC)) + .addParam(jsonObject) + .addParam(apiMetricRequest.getHash()) + .loadResults(); + + } catch (JsonProcessingException | DotDataException e) { + throw new DotRuntimeException(e); + } + } + + + /** + * Save a register with just the current time as timestamp, it is used to mark when we start + * collecting the data. + */ + public void saveStartEvent() { + try { + new DotConnect() + .setSQL("INSERT INTO metrics_temp (timestamp) VALUES (?)") + .addParam(OffsetDateTime.now(ZoneOffset.UTC)) + .loadResults(); + + } catch (DotDataException e) { + throw new DotRuntimeException(e); + } + } + + /** + * Drop all the registers on the table + */ + public void flushTemporaryTable() { + try { + new DotConnect() + .setSQL("DELETE from metrics_temp") + .loadResults(); + + } catch (DotDataException e) { + throw new DotRuntimeException(e); + } + } + + /** + * Create the metrics_temp table + * + * @throws DotDataException if something wrong happened + */ + public void createTemporaryTable() throws DotDataException { + new DotConnect().setSQL("CREATE TABLE metrics_temp (\n" + + " timestamp TIMESTAMPTZ,\n" + + " metric_type JSON,\n" + + " hash VARCHAR(255)\n" + + ")") + .loadResults(); + + saveStartEvent(); + } + + /** + * Drop the metrics_temp table + * + * @throws DotDataException if something wrong happened + */ + public void dropTemporaryTable() throws DotDataException { + new DotConnect().setSQL("DROP TABLE IF EXISTS metrics_temp").loadResults(); + } + + /** + * return the amount of hours between we start collecting the data until we are generating the + * summary + * + * @return the amount of hours + * + * @throws DotDataException An error occurred when accessing the database. + */ + @CloseDBIfOpened + @SuppressWarnings("unchecked") + private double getOverall() throws DotDataException { + final DotConnect dotConnect = new DotConnect(); + + return Double.parseDouble(((Map) dotConnect.setSQL(OVERALL_QUERY) + .loadResults() + .get(0)) + .get("overall") + .toString() + ); + } + + /** + * Return all the summary from the temporal table + * + * @return a collection of maps with the summary data. + * + * @see ApiMetricFactory + * @see ApiMetricAPI + */ + @CloseDBIfOpened + @SuppressWarnings("unchecked") + public Collection> getMetricTemporaryTableData() { + try { + final DotConnect dotConnect = new DotConnect(); + + final double overall = getOverall(); + final String sql = String.format(GET_DATA_FROM_TEMPORARY_METRIC_TABLE, overall); + + return dotConnect.setSQL(sql).loadResults(); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactorySubmitter.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactorySubmitter.java new file mode 100644 index 000000000000..c0f9ee01f553 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricFactorySubmitter.java @@ -0,0 +1,68 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotcms.concurrent.DotConcurrentFactory; +import com.dotcms.concurrent.DotSubmitter; +import com.dotmarketing.db.LocalTransaction; +import com.dotmarketing.exception.DotRuntimeException; +import com.dotmarketing.util.Config; + +/** + * Utility class for submitting a metric to be stored on the Telemetry Endpoint. All the request are + * send on async way. + */ +public enum ApiMetricFactorySubmitter { + + INSTANCE; + + static final int API_METRIC_SUBMITTER_POOL_SIZE = Config.getIntProperty( + "API_METRIC_SUBMITTER_POOL_SIZE", 1); + static final int API_METRIC_SUBMITTER_MAX_POOL_SIZE = Config.getIntProperty( + "API_METRIC_SUBMITTER_MAX_POOL_SIZE", 40); + + private DotSubmitter submitter; + + ApiMetricFactorySubmitter() { + + } + + /** + * Start the Submitter to be ready to send Metric + */ + public void start() { + final String submitterName = "MetricApiHitStorageSubmitter" + Thread.currentThread().getName(); + + submitter = DotConcurrentFactory.getInstance().getSubmitter(submitterName, + new DotConcurrentFactory.SubmitterConfigBuilder() + .poolSize(API_METRIC_SUBMITTER_POOL_SIZE) + .maxPoolSize(API_METRIC_SUBMITTER_MAX_POOL_SIZE) + .queueCapacity(Integer.MAX_VALUE) + .build() + ); + + } + + /** + * Request the telemetry endpoint asynchronously. + * + * @param metricAPIRequest request + */ + public void saveAsync(final ApiMetricRequest metricAPIRequest) { + submitter.submit(() -> save(metricAPIRequest)); + } + + private void save(final ApiMetricRequest metricAPIRequest) { + try { + LocalTransaction.wrap(() -> ApiMetricFactory.INSTANCE.save(metricAPIRequest)); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + /** + * Stop the submitter. + */ + public void shutdownNow() { + submitter.shutdownNow(); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricRequest.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricRequest.java new file mode 100644 index 000000000000..be6f42f267bd --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricRequest.java @@ -0,0 +1,70 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotcms.telemetry.Metric; + +import java.time.Instant; + +/** + * Represent a request to a Endpoint that we wish to track + * + * @see ApiMetricFactory + */ +public class ApiMetricRequest { + + private final Metric metric; + private final Instant time; + private final String hash; + + public ApiMetricRequest(final Builder builder) { + this.metric = builder.metric; + this.time = builder.time; + this.hash = builder.hash; + } + + public Metric getMetric() { + return metric; + } + + public Instant getTime() { + return time; + } + + public String getHash() { + return hash; + } + + @Override + public String toString() { + return "ApiMetricRequest{" + + "metric=" + metric + + ", time=" + time + + ", hash='" + hash + '\'' + + '}'; + } + + public static class Builder { + private Metric metric; + private Instant time; + private String hash; + + public Builder setMetric(final Metric metric) { + this.metric = metric; + return this; + } + + public Builder setTime(final Instant time) { + this.time = time; + return this; + } + + public Builder setHash(final String hash) { + this.hash = hash; + return this; + } + + public ApiMetricRequest build() { + return new ApiMetricRequest(this); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricType.java new file mode 100644 index 000000000000..34660ffb00ea --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricType.java @@ -0,0 +1,114 @@ +package com.dotcms.telemetry.collectors.api; + + +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.util.MetricCaches; +import com.dotcms.rest.api.v1.HTTPMethod; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.text.DecimalFormat; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +/** + * This class is designed to track how many times a specific API endpoint is hit. To create a metric + * that counts the number of times a particular endpoint is called, you should extend this class. + * + *

How It Works

+ *

+ * A process is in place to collect each hit on the endpoint. A listener monitors every hit and + * stores the data in a database table called metrics_temp. When metrics are calculated, the + * necessary data is retrieved from this table. If you want more details on how this process works, + * you can refer to the accompanying diagram. + *

+ * This class, or any class that extends it, is used to gather the data that will be included and + * categorized in the MetricSnapshot. The APIMetricType class overrides the getValue method from + * MetricType and also introduces new methods that can be implemented for any custom APIMetricType + * you want to create. + * + *

Method Details

+ *

+ * - getValue(): This method is overridden to filter data from the metrics_temp table based on the + * implementation of the getName, getFeature, and getCategory methods. It returns the average number + * of hits per hour for a specific endpoint. The endpoint to be monitored is determined by methods + * that each APIMetricType must implement. - getAPIUrl(): Returns a string representing the URL of + * the endpoint to monitor. The URL should be relative. For instance, if dotCMS is running at + * http://localhost:8080, and you want to track hits to the URL /contentAsset/image, you would + * return the string contentAsset/image (excluding the domain name, protocol, and port). - + * getHttpMethod(): Returns an HTTPMethod specifying which HTTP method (GET, POST, etc.) to monitor + * for the endpoint. - shouldCount(): Returns a boolean value to determine whether a specific hit + * should be counted. For example, you can set /contentAsset/image as the URL and GET as the HTTP + * method, and use this method to check for specific parameters in the request. The hit is only + * counted if the parameter is present. + *

+ * Additionally, you need to override the metadata methods getName, getCategory, and getFeature from + * MetricType, as these are not overridden by APIMetricType. + */ +public abstract class ApiMetricType implements MetricType { + + private static final DecimalFormat FORMAT = new DecimalFormat("0.##"); + + /** + * Url of the Endpoint + * + * @return the URL of the endpoint + */ + public abstract String getAPIUrl(); + + /** + * Http method of the Endpoint + * + * @return the HTTP method of the endpoint + */ + public abstract HTTPMethod getHttpMethod(); + + @Override + public final Optional getValue() { + final Optional> metricTypeItem = getMetricTypeItem(); + + return metricTypeItem.flatMap(item -> Optional.ofNullable(item.get("average_per_hour"))) + .or(() -> Optional.of(0)); + } + + /** + * Returns the unique value, indicating how many times the Endpoint was called with the same + * request. To determine if the request is the same, the method checks the following: + *
    + *
  • Query Parameters
  • + *
  • URL Parameters
  • + *
  • Request Body
  • + *
+ *

All of these need to be exactly the same to be considered the same request.

+ * + * @return the unique value + */ + public final Object getUnique() { + final double uniqueAveragePerHour = getMetricTypeItem() + .map(item -> item.get("unique_average_per_hour")) + .map(value -> Double.parseDouble(value.toString())) + .orElse(0d); + return FORMAT.format(uniqueAveragePerHour); + } + + /** + * @return + */ + private Optional> getMetricTypeItem() { + final Collection> result = MetricCaches.TEMPORARY_TABLA_DATA.get(); + + return result.stream() + .filter(item -> item.get("feature").toString().equals(getFeature().name())) + .filter(item -> item.get("category").toString().equals(getCategory().name())) + .filter(item -> item.get("name").toString().equals(getName())) + .limit(1) + .findFirst(); + } + + public boolean shouldCount(final HttpServletRequest request, + final HttpServletResponse response) { + return true; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricTypes.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricTypes.java new file mode 100644 index 000000000000..25e4c4c7f8e6 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricTypes.java @@ -0,0 +1,63 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotcms.telemetry.collectors.image.CountOfContentAssetImageBEAPICalls; +import com.dotcms.telemetry.collectors.image.CountOfContentAssetImageFEAPICalls; +import com.dotcms.telemetry.collectors.image.CountOfDAImageBEAPICalls; +import com.dotcms.telemetry.collectors.image.CountOfDAImageFEAPICalls; +import com.dotcms.rest.api.v1.HTTPMethod; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Collection of all the {@link ApiMetricType} + */ +public enum ApiMetricTypes { + + INSTANCE; + + final Collection urlToIntercept; + + ApiMetricTypes() { + urlToIntercept = new HashSet<>(); + urlToIntercept.add(new CountOfContentAssetImageFEAPICalls()); + urlToIntercept.add(new CountOfDAImageFEAPICalls()); + urlToIntercept.add(new CountOfContentAssetImageBEAPICalls()); + urlToIntercept.add(new CountOfDAImageBEAPICalls()); + + } + + public List interceptBy(final HttpServletRequest request) { + + final Optional method = getHttpMethod(request); + + if (method.isPresent()) { + final String uri = request.getRequestURI().replace("/api/", ""); + + return urlToIntercept.stream() + .filter(apiMetricType -> apiMetricType.getHttpMethod().equals(method.get()) && + uri.startsWith(apiMetricType.getAPIUrl())) + .collect(Collectors.toList()); + } + + return Collections.emptyList(); + } + + private Optional getHttpMethod(final HttpServletRequest request) { + try { + return Optional.of(HTTPMethod.valueOf(request.getMethod())); + } catch (IllegalArgumentException e) { + return Optional.empty(); + } + } + + public Collection get() { + return Collections.unmodifiableCollection(urlToIntercept); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricWebInterceptor.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricWebInterceptor.java new file mode 100644 index 000000000000..fca8932ad538 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/ApiMetricWebInterceptor.java @@ -0,0 +1,161 @@ +package com.dotcms.telemetry.collectors.api; + +import com.dotcms.filters.interceptor.Result; +import com.dotcms.filters.interceptor.WebInterceptor; +import com.liferay.util.servlet.ServletInputStreamWrapper; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Intercept all the hit to the Endpoint that we wish to track. + */ +public class ApiMetricWebInterceptor implements WebInterceptor { + + public static final ApiMetricAPI apiStatAPI = new ApiMetricAPI(); + + public ApiMetricWebInterceptor() { + ApiMetricFactorySubmitter.INSTANCE.start(); + } + + @Override + public String[] getFilters() { + return ApiMetricTypes.INSTANCE.get().stream() + .map(ApiMetricType::getAPIUrl) + .toArray(String[]::new); + + } + + @Override + public Result intercept(HttpServletRequest req, HttpServletResponse res) throws IOException { + return new Result.Builder().next() + .wrap(new RereadInputStreamRequest(req)) + .build(); + } + + @Override + public boolean afterIntercept(final HttpServletRequest req, final HttpServletResponse res) { + if (res.getStatus() == 200) { + + ApiMetricTypes.INSTANCE.interceptBy(req) + .stream() + .filter(apiMetricType -> apiMetricType.shouldCount(req, res)) + .forEach(apiMetricType -> + apiStatAPI.save(apiMetricType, (RereadInputStreamRequest) req) + ); + } + + return true; + } + + public static class RereadInputStreamRequest extends HttpServletRequestWrapper { + + private RereadAfterCloseInputStream servletInputStream; + + public RereadInputStreamRequest(final HttpServletRequest request) { + super(request); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + if (servletInputStream == null) { + servletInputStream = new RereadAfterCloseInputStream(getRequest().getInputStream()); + } + + return servletInputStream; + } + + public String getReadContent() { + int contentLength = getRequest().getContentLength(); + + if (contentLength > 0) { + return servletInputStream.getReadContent(); + } else { + return ""; + } + } + } + + /** + * This InputStream allows us to read the content multiple times as needed. It enables us to + * read the Request Body several times: once to check if the request is unique, and another time + * to process the request + */ + private static class RereadAfterCloseInputStream extends ServletInputStreamWrapper { + + final ByteArrayOutputStream byteArrayOutputStream; + private final ServletInputStream proxy; + + RereadAfterCloseInputStream(final ServletInputStream proxy) { + super(proxy); + this.proxy = proxy; + + byteArrayOutputStream = new ByteArrayOutputStream(); + } + + @Override + public int read() throws IOException { + int read = this.proxy.read(); + + if (read != -1) { + byteArrayOutputStream.write(read); + } + + return read; + } + + @Override + public int read(byte[] b) throws IOException { + int read = this.proxy.read(b); + + if (read != -1) { + byteArrayOutputStream.write(b); + } + + return read; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int read = this.proxy.read(b, off, len); + + if (read != -1) { + byteArrayOutputStream.write(b); + } + + return read; + } + + @Override + public int readLine(byte[] b, int off, int len) throws IOException { + int read = this.proxy.readLine(b, off, len); + + if (read != -1) { + byteArrayOutputStream.write(b); + } + + return read; + } + + @Override + public void close() throws IOException { + super.close(); + byteArrayOutputStream.close(); + } + + public String getReadContent() { + + if (!this.isFinished()) { + return ""; + } + + return byteArrayOutputStream.toString(); + } + + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/RequestHashCalculator.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/RequestHashCalculator.java new file mode 100644 index 000000000000..76f2b01890db --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/api/RequestHashCalculator.java @@ -0,0 +1,192 @@ +package com.dotcms.telemetry.collectors.api; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import javax.servlet.http.HttpServletRequest; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; + +/** + * Util class to provide methods to calculate a Hash from a {@link HttpServletRequest} + */ +public class RequestHashCalculator { + + final ObjectMapper jsonMapper = new ObjectMapper(); + final MessageDigest digest; + + RequestHashCalculator() { + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * Calculate a hash from a {@link HttpServletRequest} using: + *
    + *
  • The Query Parameters
  • + *
  • The body
  • + *
  • The Url Parameters
  • + *
+ *

The steps to calculate this hash are the follows: + *

    + *
  • If the Request has Query parameters the these are sort alphabetically by the + * Parameter + * Name, then 'xxx?a=1&b=2' and 'xxx?b=2&a=1' are the same. If the Request does not has any + * Query parameters then the word 'NONE' is taking instead.
  • + *
  • If the Request has Url parameters the these are sort alphabetically by the + * Parameter Name, + * then 'xxx/a/1/b/2' and 'xxx/b/2/a/1' are the same. If the Request does not has any Url + * parameters then the word 'NONE' is taking instead.
  • + *
  • If the Request has any JSON Body it is sort by alphabetically by the attribute + * name, so: + *
    +     *          {@code { a: 1, b: 2 }}
    +     *      
    + * And: + *
    +     *          {@code { b: 2, a: 1 }}
    +     *      
    + * are the same. + *
  • + *
  • Finally all of them are concat and a hash is calculated with that String.
  • + *
+ * + * @param apiMetricType + * @param request + * + * @return + */ + public String calculate(final ApiMetricType apiMetricType, + final ApiMetricWebInterceptor.RereadInputStreamRequest request) { + + final String queryParametersAsString = + getQueryParameters(request).map(Map::toString).orElse("NONE"); + final String urlParametersAsString = getUrlParameters(apiMetricType, request) + .map(Map::toString).orElse("NONE"); + final String bodyAsString = getBody(request).map(Map::toString).orElse("NONE"); + + final String requestString = queryParametersAsString + urlParametersAsString + bodyAsString; + + + final byte[] encodedHash = digest.digest(requestString.getBytes(StandardCharsets.UTF_8)); + return new String(encodedHash); + } + + @SuppressWarnings("unchecked") + private Optional> getBody(ApiMetricWebInterceptor.RereadInputStreamRequest request) { + final String requestContent = request.getReadContent(); + try { + if (!requestContent.isEmpty()) { + final Map bodyMap = jsonMapper.readValue(requestContent, + Map.class); + + return Optional.of(sort(bodyMap)); + } + + return Optional.empty(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + } + + @SuppressWarnings("unchecked") + private TreeMap sort(final Map map) { + TreeMap treeMap = new TreeMap<>(map); + + for (Map.Entry bodyMapEntry : map.entrySet()) { + final Object value = bodyMapEntry.getValue(); + + if (value instanceof Map) { + final TreeMap mapSorted = sort((Map) value); + treeMap.put(bodyMapEntry.getKey(), mapSorted); + } + } + return treeMap; + } + + + private Optional> getUrlParameters(final ApiMetricType apiMetricType, + final HttpServletRequest request) { + String uri = request.getRequestURI(); + String apiUrl = apiMetricType.getAPIUrl(); + + final String urlParameters = uri.substring(uri.indexOf("/es/search") + apiUrl.length()); + + TreeMap sortedParameters = new TreeMap<>(); + + if (urlParameters != null) { + final String[] paramsAndValues = urlParameters.split("/"); + final Pair pair = new Pair(); + + for (String paramOrValue : paramsAndValues) { + pair.add(paramOrValue); + + if (pair.isCompleted()) { + sortedParameters.put(pair.getKey(), pair.getValue()); + pair.reset(); + } + } + } + + return sortedParameters.isEmpty() ? Optional.empty() : Optional.of(sortedParameters); + } + + private Optional> getQueryParameters(final HttpServletRequest request) { + String queryString = request.getQueryString(); + + TreeMap sortedParameters = new TreeMap<>(); + + if (queryString != null) { + String[] params = queryString.split("&"); + + for (String param : params) { + String[] keyValue = param.split("="); + String key = keyValue[0]; + String value = keyValue.length > 1 ? keyValue[1] : ""; + + sortedParameters.put(key, value); + } + } + + return sortedParameters.isEmpty() ? Optional.empty() : Optional.of(sortedParameters); + } + + private static class Pair { + private String key; + private String value; + + void add(final String keyOrValue) { + if (key == null) { + key = keyOrValue; + } else { + value = keyOrValue; + } + } + + boolean isCompleted() { + return key != null && value != null; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public void reset() { + value = null; + key = null; + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLivePageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLivePageDatabaseMetricType.java new file mode 100644 index 000000000000..3ec66940f38b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLivePageDatabaseMetricType.java @@ -0,0 +1,47 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotcms.telemetry.business.MetricsAPI; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotSecurityException; +import com.dotmarketing.portlets.templates.model.Template; + +import java.util.Collection; + +/** + * Total of containers used in LIVE pages, it extends from + * {@link TotalContainersInTemplateDatabaseMetricType} because it is a counter of the containers + * used in templates is this case we want to take account just the LIVE version of each one, so it + * override the follow behavior: + *
    + *
  • Searching Templates: Override the getTemplatesIds method to return just the Template that + * has LIVE version.
  • + *
  • Retrieve the Template Version: Override the getTemplate method to get the last LIVE + * version of the Template.
  • + *
+ * + * @see TotalContainersInTemplateDatabaseMetricType + */ +public abstract class TotalContainersInLivePageDatabaseMetricType extends TotalContainersInTemplateDatabaseMetricType { + + private static final String LIVE_USED_TEMPLATES_INODES_QUERY = "SELECT " + "distinct " + + "contentlet_as_json -> 'fields' -> 'template' ->> 'value' as value " + "FROM " + + "contentlet INNER JOIN contentlet_version_info ON contentlet.inode = " + + "contentlet_version_info.live_inode " + "WHERE structure_inode IN (SELECT inode FROM " + + "structure where name = 'Page') AND " + "deleted = false"; + + private Collection getLiveUsedTemplatesInodes() { + return MetricsAPI.INSTANCE.getList(LIVE_USED_TEMPLATES_INODES_QUERY); + } + + Collection getTemplatesIds() { + return getLiveUsedTemplatesInodes(); + } + + @Override + final Template getTemplate(String id) throws DotDataException, DotSecurityException { + return APILocator.getTemplateAPI().findLiveTemplate(id, APILocator.systemUser(), false); + } + +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLiveTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLiveTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..7f9e70dfcb44 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInLiveTemplatesDatabaseMetricType.java @@ -0,0 +1,62 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotcms.telemetry.business.MetricsAPI; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotSecurityException; +import com.dotmarketing.portlets.templates.model.Template; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * This class count the amount of containers used in LIVE templates, in this case no matter the + * pages so this templates can be used or not on a page, this class extends from + * TotalContainersIntemplateDatabaseMetricType because it is a counter of the containers used in + * templates and it override the follow behavior: + *
    + *
  • Searching Templates: Override the getTemplatesIds method to return only the Template + * IDs for the LIVE templates. This is achieved using a SQL UNION query. The first part of the + * query retrieves standard templates from the template_version_info table, identifying those + * that have LIVE versions. The second part of the query retrieves file templates from the + * contenlet_version_info table, also focusing on those with live versions.
  • + *
  • Retrieve the Template Version: Override the getTemplate method to get the last LIVE + * version of the Template.
  • + *
+ */ +public abstract class TotalContainersInLiveTemplatesDatabaseMetricType extends TotalContainersInTemplateDatabaseMetricType { + + private static final String LIVE_TEMPLATES_INODES_QUERY = "SELECT DISTINCT template" + + ".identifier as value " + + "FROM template_version_info " + + "INNER JOIN template ON template_version_info.identifier = template.identifier " + + "WHERE title NOT LIKE 'anonymous_layout_%' and deleted = false"; + + private static final String LIVE_FILE_TEMPLATES_INODES_QUERY = "SELECT distinct id" + + ".parent_path as value " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path LIKE '/application/templates/%' AND id.asset_name = 'body.vtl' " + + "AND deleted = false AND live_inode is not null"; + + @Override + Collection getTemplatesIds() { + + final List dataBaseTemplateInode = + MetricsAPI.INSTANCE.getList(LIVE_TEMPLATES_INODES_QUERY); + final List dataBaseFileTemplateInode = + MetricsAPI.INSTANCE.getList(LIVE_FILE_TEMPLATES_INODES_QUERY); + + return Stream.concat(dataBaseTemplateInode.stream(), + dataBaseFileTemplateInode.stream()).collect(Collectors.toSet()); + } + + @Override + final Template getTemplate(String id) throws DotDataException, DotSecurityException { + return APILocator.getTemplateAPI() + .findLiveTemplate(id, APILocator.systemUser(), false); + } + +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInTemplateDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInTemplateDatabaseMetricType.java new file mode 100644 index 000000000000..662fef16bcb2 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInTemplateDatabaseMetricType.java @@ -0,0 +1,115 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.MetricType; +import com.dotcms.rendering.velocity.viewtools.DotTemplateTool; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotRuntimeException; +import com.dotmarketing.exception.DotSecurityException; +import com.dotmarketing.portlets.containers.model.Container; +import com.dotmarketing.portlets.templates.design.bean.ContainerUUID; +import com.dotmarketing.portlets.templates.design.bean.TemplateLayout; +import com.dotmarketing.portlets.templates.design.util.DesignTemplateUtil; +import com.dotmarketing.portlets.templates.model.Template; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Super class to use if you want to generate a Metric to count the containers Used in templates + * + * To create a metric that counts the number of containers used in templates, you need to subclass this class. + * This class overrides the getValue method to perform a search for containers, which can be customized in your implementation. + * Here's what the new implementation of the getValue method does: + * - Searching Templates: This method identifies which templates to consider. You can customize the selection by overriding + * the getTemplateIds method in your subclass. For example, you might decide to include only LIVE, WORKING, + * or Advanced Templates. To apply your own criteria for filtering templates, you need to override the getTemplateIds method. + * - Retrieve the Template Version: You can customize this step to suit your needs, such as selecting the most recent + * LIVE or WORKING version. To modify this behavior, override the getTemplate method. + * - Retrieve Containers: It gathers the containers used by each template version selected on the two previous steps. + * - Filtering Containers: The method filters the containers based on your specific requirements. + * You can also customize this step by overriding the filterContainer method in your subclass. + * + * @see TotalContainersInLivePageDatabaseMetricType + * @see TotalContainersInWorkingPageDatabaseMetricType + */ +public abstract class TotalContainersInTemplateDatabaseMetricType implements MetricType { + + @Override + public final MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public final MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public final Optional getValue() { + final Collection templatesIds = getTemplatesIds(); + final Set containersUsed = new HashSet<>(); + + try { + for (String id : templatesIds) { + final Template template = getTemplate(id); + + if (template == null) { + continue; + } + + final Collection containersId = getContainersInTemplate(template).stream() + .filter(this::filterContainer) + .collect(Collectors.toSet()); + containersUsed.addAll(containersId); + } + + return Optional.of(containersUsed.size()); + } catch (DotDataException | DotSecurityException e) { + throw new DotRuntimeException(e); + } + + + } + + abstract boolean filterContainer(final String containerId); + + public Collection getContainersInTemplate(final Template template) { + final Collection containerUUIDs; + + if(Boolean.TRUE.equals(template.isDrawed())) { + final TemplateLayout layout = template.getDrawedBody() != null ? getLayout(template.getDrawedBody()) : null; + containerUUIDs = layout != null ? APILocator.getTemplateAPI().getContainersUUID(layout) : + Collections.emptySet(); + } else { + containerUUIDs = new HashSet<>( + APILocator.getTemplateAPI().getContainersUUIDFromDrawTemplateBody(template.getBody())); + } + + return containerUUIDs.stream() + .map(ContainerUUID::getIdentifier) + .filter(identifier -> !Container.SYSTEM_CONTAINER.equals(identifier)) + .distinct() + .collect(Collectors.toList()); + } + + private TemplateLayout getLayout(final String drawedBody) { + + try { + return DotTemplateTool.getTemplateLayoutFromJSON(drawedBody); + } catch (IOException var4) { + return DesignTemplateUtil.getDesignParameters(drawedBody, false); + } + } + + abstract Collection getTemplatesIds(); + abstract Template getTemplate(final String id) throws DotDataException, DotSecurityException; +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInWorkingPageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInWorkingPageDatabaseMetricType.java new file mode 100644 index 000000000000..efd4f5c9f708 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalContainersInWorkingPageDatabaseMetricType.java @@ -0,0 +1,89 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotcms.telemetry.business.MetricsAPI; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotSecurityException; +import com.dotmarketing.portlets.templates.model.Template; + +import java.util.Collection; + +/** + * Total of containers used in Working pages. + * + * This class count the amount of containers used in WORKING pages, it means all these pages that don’t have LIVE Version, + * this class extends from {@link TotalContainersInTemplateDatabaseMetricType} because it is a counter + * of the containers used in templates is this case we want to take account just the WORKING version of each one, + * so it override the follow behavior: + * + * - Searching Templates: Override the getTemplatesIds method to return only the Template IDs for + * the templates used on a WORKING page.This is achieved using a SQL UNION query. + * The first part of the query retrieves standard templates from the template_version_info table, + * identifying those that have only a working version. + * The second part of the query retrieves file templates from the contenlet_version_info table, + * also focusing on those with just a working version. + * + * - Retrieve the Template Version: Override the getTemplate method to get the last WORKING version of the Template. + */ +public abstract class TotalContainersInWorkingPageDatabaseMetricType extends TotalContainersInTemplateDatabaseMetricType { + + private static final String WORKING_USED_TEMPLATES_INODES_QUERY = + "SELECT tvi.identifier AS value " + + "FROM template_version_info tvi " + + "INNER JOIN ( " + + "SELECT " + + "DISTINCT contentlet_as_json -> 'fields' -> 'template' ->> 'value' AS template_id, " + + "cvi.working_inode, " + + "cvi.live_inode " + + "FROM contentlet c " + + "INNER JOIN contentlet_version_info cvi ON c.inode = cvi.working_inode " + + "WHERE c.structure_inode IN (SELECT inode FROM structure WHERE name = 'Page') " + + "AND cvi.deleted = false " + + ") page ON page.template_id = tvi.identifier " + + "WHERE tvi.deleted = false " + + "AND ( " + + "(page.live_inode IS NOT NULL AND (tvi.live_inode IS NULL OR tvi.live_inode <> tvi.working_inode)) " + + "OR page.live_inode IS NULL " + + ")"; + + private static final String WORKING_USED_FILE_TEMPLATES_INODES_QUERY = + "SELECT id.id AS value " + + "FROM identifier id " + + "INNER JOIN ( " + + "SELECT contentlet_as_json->'fields'->'hostName'->>'value' hostName, identifier " + + "FROM contentlet " + + ") host ON host.identifier = id.host_inode " + + "INNER JOIN ( " + + "SELECT " + + "DISTINCT contentlet_as_json -> 'fields' -> 'template' ->> 'value' AS template_path, " + + "cvi.working_inode, " + + "cvi.live_inode " + + "FROM contentlet c " + + "INNER JOIN contentlet_version_info cvi ON c.inode = cvi.working_inode " + + "WHERE c.structure_inode IN (SELECT inode FROM structure WHERE name = 'Page') " + + "AND cvi.deleted = false " + + ") page ON page.template_path = CONCAT('//', hostName, id.parent_path) AND asset_name = 'body.vtl' " + + "INNER JOIN contentlet_version_info cvi on id.id = cvi.identifier " + + "WHERE cvi.deleted = false " + + "AND ( " + + "(page.live_inode IS NOT NULL AND (cvi.live_inode IS NULL OR cvi.live_inode <> cvi.working_inode)) " + + "OR page.live_inode IS NULL " + + ")"; + + private Collection getWorkingUsedTemplatesInodes() { + return MetricsAPI.INSTANCE.getList(WORKING_USED_TEMPLATES_INODES_QUERY + " UNION " + + WORKING_USED_FILE_TEMPLATES_INODES_QUERY); + } + + @Override + Collection getTemplatesIds() { + return getWorkingUsedTemplatesInodes(); + } + + @Override + Template getTemplate(String id) throws DotDataException, DotSecurityException { + return APILocator.getTemplateAPI() + .findWorkingTemplate(id, APILocator.systemUser(), false); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLivePageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLivePageDatabaseMetricType.java new file mode 100644 index 000000000000..2b5058cc60bf --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLivePageDatabaseMetricType.java @@ -0,0 +1,25 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of FILE containers used in LIVE pages + */ +public class TotalFileContainersInLivePageDatabaseMetricType extends TotalContainersInLivePageDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_FILE_CONTAINERS_USED_IN_LIVE_PAGES"; + } + + @Override + public String getDescription() { + return "Count of FILE containers used in LIVE pages"; + } + + @Override + boolean filterContainer(final String containerId) { + return FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLiveTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLiveTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..dd30ec4fe6c7 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInLiveTemplatesDatabaseMetricType.java @@ -0,0 +1,24 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of FILE containers used in LIVE templates + */ +public class TotalFileContainersInLiveTemplatesDatabaseMetricType extends TotalContainersInLiveTemplatesDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_FILE_CONTAINERS_USED_IN_LIVE_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Total of FILE containers used in LIVE templates"; + } + @Override + boolean filterContainer(final String containerId) { + return FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInWorkingPageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInWorkingPageDatabaseMetricType.java new file mode 100644 index 000000000000..40d1cabd2095 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalFileContainersInWorkingPageDatabaseMetricType.java @@ -0,0 +1,25 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of FILE containers used in LIVE pages + */ +public class TotalFileContainersInWorkingPageDatabaseMetricType extends TotalContainersInWorkingPageDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_FILE_CONTAINERS_USED_IN_WORKING_PAGES"; + } + + @Override + public String getDescription() { + return "Count of FILE containers used in WORKING pages"; + } + + @Override + boolean filterContainer(final String containerId) { + return FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLivePageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLivePageDatabaseMetricType.java new file mode 100644 index 000000000000..e0d09c899944 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLivePageDatabaseMetricType.java @@ -0,0 +1,25 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of STANDARD containers used in LIVE pages + */ +public class TotalStandardContainersInLivePageDatabaseMetricType extends TotalContainersInLivePageDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_STANDARD_CONTAINERS_USED_IN_LIVE_PAGES"; + } + + @Override + public String getDescription() { + return "Count of STANDARD containers used in LIVE pages"; + } + + @Override + boolean filterContainer(final String containerId) { + return !FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLiveTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLiveTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..a29555de8e2d --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInLiveTemplatesDatabaseMetricType.java @@ -0,0 +1,24 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of STANDARD containers used in LIVE templates + */ +public class TotalStandardContainersInLiveTemplatesDatabaseMetricType extends TotalContainersInLiveTemplatesDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_STANDARD_CONTAINERS_USED_IN_LIVE_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Total of STANDARD containers used in LIVE templates"; + } + @Override + boolean filterContainer(final String containerId) { + return !FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInWorkingPageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInWorkingPageDatabaseMetricType.java new file mode 100644 index 000000000000..27a1aaf75e2c --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/container/TotalStandardContainersInWorkingPageDatabaseMetricType.java @@ -0,0 +1,24 @@ +package com.dotcms.telemetry.collectors.container; + +import com.dotmarketing.portlets.containers.business.FileAssetContainerUtil; + +/** + * Total of STANDARD containers used in WORKING pages + */ +public class TotalStandardContainersInWorkingPageDatabaseMetricType extends TotalContainersInWorkingPageDatabaseMetricType { + + @Override + public String getName() { + return "COUNT_STANDARD_CONTAINERS_USED_IN_WORKING_PAGES"; + } + + @Override + public String getDescription() { + return "Count of STANDARD containers used in WORKING pages"; + } + @Override + boolean filterContainer(final String containerId) { + return !FileAssetContainerUtil.getInstance().isFolderAssetContainerId(containerId); + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LastContentEditedDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LastContentEditedDatabaseMetricType.java new file mode 100644 index 000000000000..5d04aa22d970 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LastContentEditedDatabaseMetricType.java @@ -0,0 +1,35 @@ +package com.dotcms.telemetry.collectors.content; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the modification date of the most recently edited Contentlet + */ +public class LastContentEditedDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "LAST_CONTENT_EDITED"; + } + + @Override + public String getDescription() { + return "Mod date of the most recently edited Contentlet"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENTLETS; + } + + @Override + public String getSqlQuery() { + return "SELECT to_char (max(version_ts),'HH12:MI:SS DD Mon YYYY') AS value FROM contentlet_version_info"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LiveNotDefaultLanguageContentsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LiveNotDefaultLanguageContentsDatabaseMetricType.java new file mode 100644 index 000000000000..b1b93177e8ae --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/LiveNotDefaultLanguageContentsDatabaseMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.content; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of contentlets which have at least one live version in a non-default Language + */ +public class LiveNotDefaultLanguageContentsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "LIVE_NOT_DEFAULT_LANGUAGE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Live Content items with non-default Language versions"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENTLETS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT identifier) AS value " + + "FROM contentlet_version_info " + + "WHERE live_inode IS NOT null " + + "AND lang NOT IN (SELECT default_language_id FROM company)"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/RecentlyEditedContentDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/RecentlyEditedContentDatabaseMetricType.java new file mode 100644 index 000000000000..bc439785797f --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/RecentlyEditedContentDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.content; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Contentlets that were edited less than a month ago + */ +public class RecentlyEditedContentDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "CONTENTS_RECENTLY_EDITED"; + } + + @Override + public String getDescription() { + return "Count of Contentlets that were Edited less than a month ago"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENTLETS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(working_inode) AS value FROM contentlet_version_info, contentlet " + + "WHERE contentlet.inode = contentlet_version_info.working_inode AND " + + "contentlet.mod_date > now() - interval '1 month'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/TotalContentsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/TotalContentsDatabaseMetricType.java new file mode 100644 index 000000000000..1b0fc6744d30 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/TotalContentsDatabaseMetricType.java @@ -0,0 +1,35 @@ +package com.dotcms.telemetry.collectors.content; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total number of contentlets + */ +public class TotalContentsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT"; + } + + @Override + public String getDescription() { + return "Total number of Contentlets"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENTLETS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(working_inode) AS value FROM contentlet_version_info"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/WorkingNotDefaultLanguageContentsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/WorkingNotDefaultLanguageContentsDatabaseMetricType.java new file mode 100644 index 000000000000..3f568e45e9fe --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/content/WorkingNotDefaultLanguageContentsDatabaseMetricType.java @@ -0,0 +1,44 @@ +package com.dotcms.telemetry.collectors.content; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of Contentlets that has at least one working version on any non-default language and that + * also don't have live version on any non-default language + */ +public class WorkingNotDefaultLanguageContentsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "WORKING_NOT_DEFAULT_LANGUAGE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Working Content items with non-default Language versions"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENTLETS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT identifier) AS value " + + "FROM contentlet_version_info AS cvi1 " + + "WHERE working_inode is not null and live_inode is null " + + "AND lang NOT IN (SELECT default_language_id FROM company) " + + "AND (SELECT COUNT(DISTINCT identifier) " + + "FROM contentlet_version_info AS cvi2 " + + "WHERE live_inode IS NOT null " + + "AND cvi1.identifier = cvi2.identifier " + + "AND lang NOT IN (SELECT default_language_id FROM company) ) = 0"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/ContentTypeFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/ContentTypeFieldsMetricType.java new file mode 100644 index 000000000000..65fdf23b3654 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/ContentTypeFieldsMetricType.java @@ -0,0 +1,64 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.MetricValue; +import com.dotmarketing.common.db.DotConnect; +import com.dotmarketing.db.LocalTransaction; +import com.dotmarketing.exception.DotRuntimeException; + +import javax.ws.rs.NotSupportedException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Collects the total number of contentlets + */ +public abstract class ContentTypeFieldsMetricType implements MetricType { + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.CONTENT_TYPE_FIELDS; + } + + @Override + public Optional getStat() { + try { + return LocalTransaction.wrapReturn(() -> { + final String sqlQuery = "SELECT field_type, count(*)\n" + + "FROM field GROUP BY field_type"; + final DotConnect dotConnect = new DotConnect(); + final List> loadObjectResults = dotConnect.setSQL(sqlQuery) + .loadObjectResults(); + + return getValue(loadObjectResults) + .map(o -> new MetricValue(this.getMetric(), o)) + .or(() -> Optional.of(new MetricValue(this.getMetric(), 0))); + }); + } catch (Exception e) { + throw new DotRuntimeException(e); + } + } + + @Override + public Optional getValue() { + throw new NotSupportedException(); + } + + abstract boolean filterCondition(Map map); + + Optional getValue(List> results) { + return Optional.of(results.stream() + .filter(this::filterCondition) + .map(m -> m.get("count")) + .findFirst() + .orElse(0)); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBinaryFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBinaryFieldsMetricType.java new file mode 100644 index 000000000000..24e2227fec80 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBinaryFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfBinaryFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.BinaryField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_BINARY_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of binary fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBlockEditorFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBlockEditorFieldsMetricType.java new file mode 100644 index 000000000000..ddf230571c02 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfBlockEditorFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfBlockEditorFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.StoryBlockField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_BLOCK_EDITOR_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of block editor fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCategoryFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCategoryFieldsMetricType.java new file mode 100644 index 000000000000..e9b0c6bff5f4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCategoryFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfCategoryFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.CategoryField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_CATEGORY_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of category fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCheckboxFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCheckboxFieldsMetricType.java new file mode 100644 index 000000000000..a351d188229d --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfCheckboxFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfCheckboxFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.CheckboxField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_CHECKBOX_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of checkbox fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfColumnsFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfColumnsFieldsMetricType.java new file mode 100644 index 000000000000..8b16c4b4d470 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfColumnsFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfColumnsFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.ColumnField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_COLUMN_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of column fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfConstantFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfConstantFieldsMetricType.java new file mode 100644 index 000000000000..d1aff0016ef4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfConstantFieldsMetricType.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfConstantFieldsMetricType extends ContentTypeFieldsMetricType { + @Override + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.ConstantField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_CONSTANT_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of constant fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateFieldsMetricType.java new file mode 100644 index 000000000000..fa781af8ad1d --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateFieldsMetricType.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfDateFieldsMetricType extends ContentTypeFieldsMetricType { + @Override + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.DateField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_DATE_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of date fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateTimeFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateTimeFieldsMetricType.java new file mode 100644 index 000000000000..c9629a8a7e38 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfDateTimeFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfDateTimeFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.DateTimeField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_DATE_TIME_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of date time fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfFileFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfFileFieldsMetricType.java new file mode 100644 index 000000000000..b0bfae4c0a17 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfFileFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfFileFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.FileField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_FILE_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of file fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfHiddenFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfHiddenFieldsMetricType.java new file mode 100644 index 000000000000..071977c25d73 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfHiddenFieldsMetricType.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfHiddenFieldsMetricType extends ContentTypeFieldsMetricType { + @Override + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.HiddenField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_HIDDEN_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of hidden fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfImageFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfImageFieldsMetricType.java new file mode 100644 index 000000000000..1ab981d48d15 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfImageFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfImageFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.ImageField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_IMAGE_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of image fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfJSONFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfJSONFieldsMetricType.java new file mode 100644 index 000000000000..7bd347c9bcf8 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfJSONFieldsMetricType.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfJSONFieldsMetricType extends ContentTypeFieldsMetricType { + @Override + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.JSONField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_JSON_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of JSON fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfKeyValueFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfKeyValueFieldsMetricType.java new file mode 100644 index 000000000000..c0b5b1448506 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfKeyValueFieldsMetricType.java @@ -0,0 +1,20 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfKeyValueFieldsMetricType extends ContentTypeFieldsMetricType { + @Override + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.KeyValueField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_KEY_VALUE_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of key/value fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfLineDividersFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfLineDividersFieldsMetricType.java new file mode 100644 index 000000000000..9769d5ab64a4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfLineDividersFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfLineDividersFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.LineDividerField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_LINE_DIVIDER_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of line divider fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfMultiselectFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfMultiselectFieldsMetricType.java new file mode 100644 index 000000000000..5888ca841a66 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfMultiselectFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfMultiselectFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.MultiSelectField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_MULTI_SELECT_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of multi select fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfPermissionsFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfPermissionsFieldsMetricType.java new file mode 100644 index 000000000000..a3f0b59d8d56 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfPermissionsFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfPermissionsFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.PermissionTabField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_PERMISSIONS_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of permissions fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRadioFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRadioFieldsMetricType.java new file mode 100644 index 000000000000..ceabb66da02b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRadioFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfRadioFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.RadioField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_RADIO_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of radio fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRelationshipFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRelationshipFieldsMetricType.java new file mode 100644 index 000000000000..65a3e95ed283 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRelationshipFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfRelationshipFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.RelationshipField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_RELATIONSHIP_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of relationship fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRowsFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRowsFieldsMetricType.java new file mode 100644 index 000000000000..b3f8e35ec68e --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfRowsFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfRowsFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.RowField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_ROW_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of row fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSelectFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSelectFieldsMetricType.java new file mode 100644 index 000000000000..cb0cbec5d04f --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSelectFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfSelectFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.SelectField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_SELECT_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of select fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSiteOrFolderFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSiteOrFolderFieldsMetricType.java new file mode 100644 index 000000000000..f3e4f20585aa --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfSiteOrFolderFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfSiteOrFolderFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.HostFolderField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_SITE_OR_FOLDER_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of site or folder fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTabFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTabFieldsMetricType.java new file mode 100644 index 000000000000..b3bb6e76ef6c --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTabFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfTabFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.TabDividerField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_TAB_DIVIDER_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of tab divider fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTagFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTagFieldsMetricType.java new file mode 100644 index 000000000000..06da4b0e9aa9 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTagFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfTagFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.TagField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_TAG_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of tag fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextAreaFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextAreaFieldsMetricType.java new file mode 100644 index 000000000000..d9bf584040c4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextAreaFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfTextAreaFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.TextAreaField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_TEXT_AREA_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of text area fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextFieldsMetricType.java new file mode 100644 index 000000000000..dd96246b2672 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTextFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfTextFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.TextField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_TEXT_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of text fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTimeFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTimeFieldsMetricType.java new file mode 100644 index 000000000000..ec67e4791a8f --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfTimeFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfTimeFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.TimeField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_TIME_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of time fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfWYSIWYGFieldsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfWYSIWYGFieldsMetricType.java new file mode 100644 index 000000000000..1319d4f30b0b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/contenttype/CountOfWYSIWYGFieldsMetricType.java @@ -0,0 +1,19 @@ +package com.dotcms.telemetry.collectors.contenttype; + +import java.util.Map; + +public class CountOfWYSIWYGFieldsMetricType extends ContentTypeFieldsMetricType { + boolean filterCondition(Map map) { + return "com.dotcms.contenttype.model.field.WysiwygField".equals(map.get("field_type")); + } + + @Override + public String getName() { + return "COUNT_WYSIWYG_FIELDS"; + } + + @Override + public String getDescription() { + return "Count the number of WYSIWYG fields"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageBEAPICalls.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageBEAPICalls.java new file mode 100644 index 000000000000..7d1203965dc4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageBEAPICalls.java @@ -0,0 +1,58 @@ +package com.dotcms.telemetry.collectors.image; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.api.ApiMetricType; +import com.dotcms.rest.api.v1.HTTPMethod; +import com.dotmarketing.util.PageMode; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Represents a Metric to count how many times the Endpoint '/contentAsset/image/' is called from + * Back End. + */ +public class CountOfContentAssetImageBEAPICalls extends ApiMetricType { + + @Override + public String getName() { + return "COUNT_OF_BE_CONTENTASSET_CALLS"; + } + + @Override + public String getDescription() { + return "Count of 'contentAsset/image' API calls from Back End"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.IMAGE_API; + } + + + @Override + public String getAPIUrl() { + return "/contentAsset/image/"; + } + + @Override + public HTTPMethod getHttpMethod() { + return HTTPMethod.GET; + } + + @Override + @JsonIgnore + public boolean shouldCount(final HttpServletRequest request, + final HttpServletResponse response) { + final PageMode currentPageMode = PageMode.get(request); + return currentPageMode != PageMode.LIVE; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageFEAPICalls.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageFEAPICalls.java new file mode 100644 index 000000000000..98c4198f3052 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfContentAssetImageFEAPICalls.java @@ -0,0 +1,58 @@ +package com.dotcms.telemetry.collectors.image; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.api.ApiMetricType; +import com.dotcms.rest.api.v1.HTTPMethod; +import com.dotmarketing.util.PageMode; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Represents a Metric to count how many times the Endpoint '/contentAsset/image/' is called from + * Front End. + */ +public class CountOfContentAssetImageFEAPICalls extends ApiMetricType { + + @Override + public String getName() { + return "COUNT_OF_FE_CONTENTASSET_CALLS"; + } + + @Override + public String getDescription() { + return "Count of 'contentAsset/image' API calls from Front End"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.IMAGE_API; + } + + + @Override + public String getAPIUrl() { + return "/contentAsset/image/"; + } + + @Override + public HTTPMethod getHttpMethod() { + return HTTPMethod.GET; + } + + @Override + @JsonIgnore + public boolean shouldCount(final HttpServletRequest request, + final HttpServletResponse response) { + final PageMode currentPageMode = PageMode.get(request); + return currentPageMode == PageMode.LIVE; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageBEAPICalls.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageBEAPICalls.java new file mode 100644 index 000000000000..6cf01edb06bd --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageBEAPICalls.java @@ -0,0 +1,57 @@ +package com.dotcms.telemetry.collectors.image; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.api.ApiMetricType; +import com.dotcms.rest.api.v1.HTTPMethod; +import com.dotmarketing.util.PageMode; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Represents a Metric to count how many times the Endpoint '/dA' is called From Back End. + */ +public class CountOfDAImageBEAPICalls extends ApiMetricType { + + @Override + public String getName() { + return "COUNT_OF_BE_DA_CALLS"; + } + + @Override + public String getDescription() { + return "Count of '/dA/' API calls From Back End"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.IMAGE_API; + } + + + @Override + public String getAPIUrl() { + return "/dA/"; + } + + @Override + public HTTPMethod getHttpMethod() { + return HTTPMethod.GET; + } + + @Override + @JsonIgnore + public boolean shouldCount(final HttpServletRequest request, + final HttpServletResponse response) { + final PageMode currentPageMode = PageMode.get(request); + return currentPageMode != PageMode.LIVE; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageFEAPICalls.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageFEAPICalls.java new file mode 100644 index 000000000000..49e8ca78b077 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/image/CountOfDAImageFEAPICalls.java @@ -0,0 +1,57 @@ +package com.dotcms.telemetry.collectors.image; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.api.ApiMetricType; +import com.dotcms.rest.api.v1.HTTPMethod; +import com.dotmarketing.util.PageMode; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Represents a Metric to count how many times the Endpoint '/dA' is called from Front End. + */ +public class CountOfDAImageFEAPICalls extends ApiMetricType { + + @Override + public String getName() { + return "COUNT_OF_FE_DA_CALLS"; + } + + @Override + public String getDescription() { + return "Count of '/dA/' API calls From Front End"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.IMAGE_API; + } + + + @Override + public String getAPIUrl() { + return "/dA/"; + } + + @Override + public HTTPMethod getHttpMethod() { + return HTTPMethod.GET; + } + + @Override + @JsonIgnore + public boolean shouldCount(final HttpServletRequest request, + final HttpServletResponse response) { + final PageMode currentPageMode = PageMode.get(request); + return currentPageMode == PageMode.LIVE; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/HasChangeDefaultLanguagesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/HasChangeDefaultLanguagesDatabaseMetricType.java new file mode 100644 index 000000000000..211c322269c6 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/HasChangeDefaultLanguagesDatabaseMetricType.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Checks if the default language was changed from English + */ +public class HasChangeDefaultLanguagesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "IS_DEFAULT_LANGUAGE_NOT_ENGLISH"; + } + + @Override + public String getDescription() { + return "Has default language been changed from English?"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public String getSqlQuery() { + return "SELECT language_code <> 'en' AS value FROM language " + + "WHERE id IN (SELECT default_language_id FROM company)"; + } +} \ No newline at end of file diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/OldStyleLanguagesVarialeMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/OldStyleLanguagesVarialeMetricType.java new file mode 100644 index 000000000000..dfda412a742b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/OldStyleLanguagesVarialeMetricType.java @@ -0,0 +1,56 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.MetricType; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.portlets.languagesmanager.business.LanguageAPI; +import com.dotmarketing.portlets.languagesmanager.model.Language; +import com.dotmarketing.portlets.languagesmanager.model.LanguageKey; + +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Collects the count of old style Language Variables + */ + +public class OldStyleLanguagesVarialeMetricType implements MetricType { + + @Override + public String getName() { + return "OLD_STYLE_LANGUAGES_VARIABLE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of old-style Language variables"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public Optional getValue() { + + final LanguageAPI languageAPI = APILocator.getLanguageAPI(); + + final Set languagesCodes = languageAPI.getLanguages().stream() + .map(Language::getLanguageCode) + .collect(Collectors.toSet()); + + final Set oldStyleLanguageKey = languagesCodes.stream().flatMap(languagesCode -> languageAPI.getLanguageKeys(languagesCode).stream()) + .map(LanguageKey::getKey) + .collect(Collectors.toSet()); + + return Optional.of(oldStyleLanguageKey.size()); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLanguagesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLanguagesDatabaseMetricType.java new file mode 100644 index 000000000000..b1080c0396ad --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLanguagesDatabaseMetricType.java @@ -0,0 +1,35 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of languages + */ +public class TotalLanguagesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT"; + } + + @Override + public String getDescription() { + return "Count of configured dotCMS Languages"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(*) AS value FROM language"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLiveLanguagesVariablesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLiveLanguagesVariablesDatabaseMetricType.java new file mode 100644 index 000000000000..67aa40715128 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalLiveLanguagesVariablesDatabaseMetricType.java @@ -0,0 +1,39 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.contenttype.model.type.BaseContentType; +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of Language Variables that have a live version. + */ +public class TotalLiveLanguagesVariablesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "LIVE_LANGUAGE_VARIABLE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Live Language Variables"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct contentlet.identifier) AS value FROM contentlet " + + "INNER JOIN structure ON contentlet.structure_inode=structure.inode " + + "INNER JOIN contentlet_version_info ON contentlet.identifier = contentlet_version_info.identifier " + + "WHERE structuretype = " + BaseContentType.KEY_VALUE.getType() + " AND deleted = false AND live_inode IS NOT null"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalUniqueLanguagesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalUniqueLanguagesDatabaseMetricType.java new file mode 100644 index 000000000000..158b677298e1 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalUniqueLanguagesDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of unique configured dotCMS Languages, it means that if two o more Countries use the same + * language then it just count as one + */ +public class TotalUniqueLanguagesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "UNIQUE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of unique configured dotCMS Languages, it means that if two o more Countries use the same " + + "language then it just count as one"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT language_code) AS value FROM language"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalWorkingLanguagesVariablesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalWorkingLanguagesVariablesDatabaseMetricType.java new file mode 100644 index 000000000000..f62a60c3183a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/language/TotalWorkingLanguagesVariablesDatabaseMetricType.java @@ -0,0 +1,44 @@ +package com.dotcms.telemetry.collectors.language; + +import com.dotcms.contenttype.model.type.BaseContentType; +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Language Variable that does not have Live Version. + */ +public class TotalWorkingLanguagesVariablesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "WORKING_LANGUAGE_VARIABLE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Working Language Variables"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LANGUAGES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct c.identifier) AS value " + + "FROM contentlet AS c " + + "INNER JOIN structure ON c.structure_inode=structure.inode " + + "INNER JOIN contentlet_version_info ON c.identifier = contentlet_version_info.identifier " + + "WHERE structuretype = " + BaseContentType.KEY_VALUE.getType() + " AND deleted = false AND live_inode is null " + + "AND working_inode IS NOT null AND (SELECT COUNT(DISTINCT identifier) " + + "FROM contentlet_version_info AS cvi2 " + + "WHERE live_inode IS NOT null " + + "AND c.identifier = cvi2.identifier) = 0"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfLiveSitesWithSiteVariablesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfLiveSitesWithSiteVariablesMetricType.java new file mode 100644 index 000000000000..9a1aaeaeaa71 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfLiveSitesWithSiteVariablesMetricType.java @@ -0,0 +1,16 @@ +package com.dotcms.telemetry.collectors.site; + +/** + * Collects the count of started (live) Sites that have Site Variables. + * + * @author Jose Castro + * @since Oct 4th, 2024 + */ +public class CountOfLiveSitesWithSiteVariablesMetricType extends CountOfSitesWithSiteVariablesMetricType { + + @Override + public PublishStatus getPublishStatus() { + return PublishStatus.LIVE; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithIndividualPermissionsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithIndividualPermissionsMetricType.java new file mode 100644 index 000000000000..f5634e6390d2 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithIndividualPermissionsMetricType.java @@ -0,0 +1,43 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of sites with permissions not inheriting from System Host + */ +public class CountOfSitesWithIndividualPermissionsMetricType implements DBMetricType { + + + @Override + public String getName() { + return "SITES_WITH_INDIVIDUAL_PERMISSIONS"; + } + + @Override + public String getDescription() { + return "Count of sites with permissions not inheriting from System Host"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT c.identifier) AS value\n" + + "FROM contentlet c JOIN structure s\n" + + " ON c.structure_inode = s.inode\n" + + " JOIN contentlet_version_info cvi\n" + + " ON (c.inode = cvi.working_inode OR c.inode = cvi.live_inode)\n" + + "WHERE s.name = 'Host' AND c.identifier <> 'SYSTEM_HOST'\n" + + "AND (SELECT COUNT(*) AS cc FROM permission where inode_id=c.identifier) > 0;"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithSiteVariablesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithSiteVariablesMetricType.java new file mode 100644 index 000000000000..f30fd752c0d3 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithSiteVariablesMetricType.java @@ -0,0 +1,74 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of Sites that have Site Variables. + * + * @author Jose Castro + * @since Oct 4th, 2024 + */ +public abstract class CountOfSitesWithSiteVariablesMetricType implements DBMetricType { + + @Override + public String getName() { + return "WITH_" + getPublishStatus().name() + "_SITE_VARIABLES"; + } + + @Override + public String getDescription() { + return "Count of " + getPublishStatus().getName() + " Sites that have Site Variables"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(identifier) AS value FROM contentlet_version_info WHERE deleted IS FALSE AND " + + getPublishStatus().getCondition() + " AND identifier IN (SELECT DISTINCT " + + "host_id FROM host_variable)"; + } + + /** + * Allows you to specify whether you want to collect Metrics from a started or stopped Site. + * + * @return The {@link PublishStatus} used to generate the metrics. + */ + public abstract PublishStatus getPublishStatus(); + + /** + * Determines the publish status of a given Site: Started (live) or Stopped (working). + */ + public enum PublishStatus { + WORKING("Working", "(working_inode <> live_inode OR live_inode IS NULL)"), + LIVE("Live", "working_inode = live_inode"); + + private final String name; + private final String condition; + + PublishStatus(final String value, final String condition) { + this.name = value; + this.condition = condition; + } + + public String getName() { + return name; + } + + public String getCondition() { + return condition; + } + + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithThumbnailsMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithThumbnailsMetricType.java new file mode 100644 index 000000000000..fb2cba1a0c3c --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfSitesWithThumbnailsMetricType.java @@ -0,0 +1,84 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.MetricType; +import com.dotmarketing.beans.Host; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.common.db.DotConnect; +import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.util.Logger; +import io.vavr.control.Try; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Collects the count of sites with thumbnails set + */ +public class CountOfSitesWithThumbnailsMetricType implements MetricType { + + private static final String ALL_SITES_INODES = "SELECT c.inode AS inode \n" + + "FROM contentlet c JOIN structure s\n" + + "ON c.structure_inode = s.inode\n" + + "JOIN contentlet_version_info cvi\n" + + "ON (c.inode = cvi.working_inode)\n" + + "WHERE s.name = 'Host' AND c.identifier <> 'SYSTEM_HOST';\n"; + + + @Override + public String getName() { + return "SITES_WITH_THUMBNAIL_COUNT"; + } + + @Override + public String getDescription() { + return "Count of sites with Thumbnails"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public Optional getValue() { + return Optional.of(getCountOfSitesWithThumbnails()); + } + + private int getCountOfSitesWithThumbnails() { + int hostsWithThumbnailsCount = 0; + + try { + final List allSitesInodes = getAllSitesInodes(); + + for (String siteInode : allSitesInodes) { + final File hostThumbnail = Try.of(() -> APILocator.getContentletAPI().getBinaryFile(siteInode, + Host.HOST_THUMB_KEY, APILocator.systemUser())).getOrNull(); + if (hostThumbnail != null) { + hostsWithThumbnailsCount++; + } + } + + } catch(Exception e) { + Logger.debug(this, "Error counting Sites with thumbnails"); + } + + return hostsWithThumbnailsCount; + } + + private List getAllSitesInodes() throws DotDataException { + final DotConnect db = new DotConnect(); + final List> results = db.setSQL(ALL_SITES_INODES).loadObjectResults(); + return results.stream().map(map -> (String) map.get("inode")).collect(Collectors.toList()); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfWorkingSitesWithSiteVariablesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfWorkingSitesWithSiteVariablesMetricType.java new file mode 100644 index 000000000000..16a6898719a6 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/CountOfWorkingSitesWithSiteVariablesMetricType.java @@ -0,0 +1,16 @@ +package com.dotcms.telemetry.collectors.site; + +/** + * Collects the count of stopped (working) Sites that have Site Variables. + * + * @author Jose Castro + * @since Oct 4th, 2024 + */ +public class CountOfWorkingSitesWithSiteVariablesMetricType extends CountOfSitesWithSiteVariablesMetricType { + + @Override + public PublishStatus getPublishStatus() { + return PublishStatus.WORKING; + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoDefaultTagStorageDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoDefaultTagStorageDatabaseMetricType.java new file mode 100644 index 000000000000..bef3d73390d7 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoDefaultTagStorageDatabaseMetricType.java @@ -0,0 +1,49 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of sites With non-default value on the tagStorage attribute + */ +public class SitesWithNoDefaultTagStorageDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "SITES_NON_DEFAULT_TAG_STORAGE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Sites With Not Default value on the tagStorage attribute"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct c.identifier) AS value\n" + + "FROM contentlet c\n" + + " JOIN structure s ON c.structure_inode = s.inode\n" + + " JOIN contentlet_version_info cvi on (c.inode = cvi.working_inode OR c.inode = cvi.live_inode)\n" + + " WHERE s.name = 'Host'\n" + + " AND c.identifier <> 'SYSTEM_HOST'\n" + + " AND c.contentlet_as_json -> 'fields' -> 'tagStorage' ->> 'value' <>\n" + + " -- DEFAULT_HOST identifier\n" + + " (SELECT distinct c.identifier\n" + + " FROM contentlet c\n" + + " JOIN structure s ON c.structure_inode = s.inode\n" + + " JOIN contentlet_version_info cvi\n" + + " on (c.inode = cvi.working_inode OR c.inode = cvi.live_inode)\n" + + " WHERE s.name = 'Host'\n" + + " AND c.contentlet_as_json -> 'fields' -> 'isDefault' ->> 'value' = 'true')"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoSystemFieldsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoSystemFieldsDatabaseMetricType.java new file mode 100644 index 000000000000..0558308ed33e --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithNoSystemFieldsDatabaseMetricType.java @@ -0,0 +1,40 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of non-system fields in Host content type + */ +public class SitesWithNoSystemFieldsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "NON_SYSTEM_FIELDS_ON_CONTENT_TYPE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of non-system fields in Host content type"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT count(f.inode) AS value\n" + + "FROM field f, structure s WHERE f.structure_inode = s.inode\n" + + "AND s.name = 'Host'\n" + + "AND f.fixed = false\n" + + "AND field_type <> 'com.dotcms.contenttype.model.field.RowField'\n" + + "AND field_type <> 'com.dotcms.contenttype.model.field.ColumnField'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithRunDashboardDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithRunDashboardDatabaseMetricType.java new file mode 100644 index 000000000000..0906c021cdb1 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/SitesWithRunDashboardDatabaseMetricType.java @@ -0,0 +1,40 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of sites with 'Run Dashboard' enabled + */ +public class SitesWithRunDashboardDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "SITES_RUN_DASHBOARD_TRUE_COUNT"; + } + + @Override + public String getDescription() { + return "Count of sites with 'Run Dashboard' enabled"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + public String getSqlQuery() { + return "SELECT COUNT(c.identifier)\n" + + " AS value FROM contentlet c\n" + + " JOIN structure s ON c.structure_inode = s.inode\n" + + " JOIN contentlet_version_info cvi on (c.inode = cvi.working_inode OR c.inode = cvi.live_inode)\n" + + " WHERE s.name = 'Host'\n" + + " AND c.identifier <> 'SYSTEM_HOST'\n" + + " AND c.contentlet_as_json -> 'fields' -> 'runDashboard' ->> 'value' = 'true'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalActiveSitesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalActiveSitesDatabaseMetricType.java new file mode 100644 index 000000000000..fcfc902dde56 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalActiveSitesDatabaseMetricType.java @@ -0,0 +1,40 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of active sites + */ +public class TotalActiveSitesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_ACTIVE_SITES"; + } + + @Override + public String getDescription() { + return "Total count of active sites"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(id) as value\n" + + "FROM identifier i\n" + + "JOIN contentlet_version_info cvi ON i.id = cvi.identifier\n" + + "WHERE asset_subtype = 'Host'\n" + + " AND id <> 'SYSTEM_HOST'\n" + + "AND cvi.live_inode is not null"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesActiveSitesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesActiveSitesDatabaseMetricType.java new file mode 100644 index 000000000000..840eb0cc404e --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesActiveSitesDatabaseMetricType.java @@ -0,0 +1,43 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of aliases on all active sites + */ +public class TotalAliasesActiveSitesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "ALIASES_ACTIVE_SITES_COUNT"; + } + + @Override + public String getDescription() { + return "Count of aliases on all active sites"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT coalesce(SUM(array_length(regexp_split_to_array(trim(result.aliases), '[\\n\\r\\t]'), 1)),0) AS value\n" + + "FROM (SELECT c.contentlet_as_json -> 'fields' -> 'aliases' ->> 'value' AS aliases\n" + + " FROM contentlet c\n" + + " JOIN structure s on c.structure_inode = s.inode JOIN contentlet_version_info\n" + + " cvi on c.inode = cvi.live_inode\n" + + " WHERE s.name = 'Host' AND cvi.live_inode is not null\n" + + " AND c.contentlet_as_json -> 'fields' -> 'hostName' ->> 'value' <> 'System Host')\n" + + " AS result\n" + + "WHERE result.aliases <> ''\n"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesAllSitesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesAllSitesDatabaseMetricType.java new file mode 100644 index 000000000000..66d4cafaf321 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalAliasesAllSitesDatabaseMetricType.java @@ -0,0 +1,43 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of aliases on all sites + */ +public class TotalAliasesAllSitesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "ALIASES_SITES_COUNT"; + } + + @Override + public String getDescription() { + return "Count of aliases on all sites"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT coalesce(SUM(array_length(regexp_split_to_array(trim(result.aliases), '[\\n\\r\\t]'), 1)),0) AS value\n" + + "FROM (SELECT c.contentlet_as_json -> 'fields' -> 'aliases' ->> 'value' AS aliases\n" + + " FROM contentlet c\n" + + " JOIN structure s on c.structure_inode = s.inode JOIN contentlet_version_info\n" + + " cvi on (c.inode = cvi.working_inode OR c.inode = cvi.live_inode)\n" + + " WHERE s.name = 'Host' \n" + + " AND c.contentlet_as_json -> 'fields' -> 'hostName' ->> 'value' <> 'System Host')\n" + + " AS result\n" + + "WHERE result.aliases <> ''\n"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalSitesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalSitesDatabaseMetricType.java new file mode 100644 index 000000000000..8c25dd657616 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/site/TotalSitesDatabaseMetricType.java @@ -0,0 +1,35 @@ +package com.dotcms.telemetry.collectors.site; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of sites + */ +public class TotalSitesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_SITES"; + } + + @Override + public String getDescription() { + return "Total count of sites"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.SITES; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(id) as value FROM identifier WHERE asset_subtype='Host' AND id <> 'SYSTEM_HOST'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchDocumentMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchDocumentMetricType.java new file mode 100644 index 000000000000..7f3d3cabc807 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchDocumentMetricType.java @@ -0,0 +1,32 @@ +package com.dotcms.telemetry.collectors.sitesearch; + +import com.dotcms.content.elasticsearch.business.IndexStats; +import com.dotmarketing.exception.DotDataException; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Collects the number of documents in all site search indexes. + */ +public class CountSiteSearchDocumentMetricType extends IndicesSiteSearchMetricType { + + + @Override + public String getName() { + return "INDICES_DOCUMENT_COUNT"; + } + + @Override + public String getDescription() { + return "Number of documents in indexes"; + } + + @Override + public Optional getValue(Collection indices) throws DotDataException { + return Optional.of(indices.stream() + .collect(Collectors.summingLong(IndexStats::getDocumentCount)) + ); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchIndicesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchIndicesMetricType.java new file mode 100644 index 000000000000..83a392a1ce72 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/CountSiteSearchIndicesMetricType.java @@ -0,0 +1,29 @@ +package com.dotcms.telemetry.collectors.sitesearch; + +import com.dotcms.content.elasticsearch.business.IndexStats; +import com.dotmarketing.exception.DotDataException; + +import java.util.Collection; +import java.util.Optional; + +/** + * Collect the count of Site Search indices + */ +public class CountSiteSearchIndicesMetricType extends IndicesSiteSearchMetricType { + + + @Override + public String getName() { + return "INDICES_COUNT"; + } + + @Override + public String getDescription() { + return "Count of indexes"; + } + + @Override + public Optional getValue(Collection indices) throws DotDataException { + return Optional.of(indices.size()); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/IndicesSiteSearchMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/IndicesSiteSearchMetricType.java new file mode 100644 index 000000000000..af9dcc43d626 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/IndicesSiteSearchMetricType.java @@ -0,0 +1,68 @@ +package com.dotcms.telemetry.collectors.sitesearch; + +import com.dotcms.content.elasticsearch.business.IndexStats; +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.MetricValue; +import com.dotcms.telemetry.util.MetricCaches; +import com.dotmarketing.exception.DotDataException; + +import javax.ws.rs.NotSupportedException; +import java.util.Collection; +import java.util.Optional; + +/** + * This class represents any Metric that requires Site Search Index information for its calculation. + * Any Metric that relies on the Site Search index must extend from this class. + * + *

Overridden Methods:

+ * + * - getStat: This method is called when collecting the Metric values. It relies on a getValue method, + * which is overridden by each subclass of MetricType. In this class, getStat uses its own version of getValue, + * necessitating the override. + * + * - getValue: This method is overridden to throw a NotSupportedException. As mentioned earlier, + * this class does not use this method to calculate values; instead, it uses a different getValue method. + * + * - getValue(final Collection indices): This is the actual getValue method used by the getStat method. + * The getStat method first retrieves the indices information and then calls this getValue method to calculate the Metric's value. + * + *

In Summary:

+ * The getStat method works as follows: + * - Retrieves Site Search Indices Information: It uses the Elasticsearch Client Utility class to send a request to the + * Elasticsearch server and retrieve the indices information. + * - Caches the Site Search Indices Information: This information is stored in a cache. If multiple classes need this + * information, the request to the Elasticsearch server is made only once. Each MetricType then uses the cached information. + * The cache is cleared when all Metrics are calculated. + * - Calls the getValue(final Collection indices) Method: This method calculates the Metric value. + * It must be overridden by each concrete class that extends from this class. + * + * @see MetricType + */ +public abstract class IndicesSiteSearchMetricType implements MetricType { + + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + public MetricFeature getFeature() { + return MetricFeature.SITE_SEARCH; + } + + @Override + public Optional getStat() throws DotDataException { + return getValue(MetricCaches.SITE_SEARCH_INDICES.get()) + .map(o -> new MetricValue(this.getMetric(), o)) + .or(() -> Optional.of(new MetricValue(this.getMetric(), 0))); + + } + + @Override + public Optional getValue() { + throw new NotSupportedException(); + } + + abstract Optional getValue(final Collection indices) throws DotDataException; + + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/TotalSizeSiteSearchIndicesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/TotalSizeSiteSearchIndicesMetricType.java new file mode 100644 index 000000000000..af93df6bfd02 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/sitesearch/TotalSizeSiteSearchIndicesMetricType.java @@ -0,0 +1,33 @@ +package com.dotcms.telemetry.collectors.sitesearch; + +import com.dotcms.content.elasticsearch.business.IndexStats; +import com.dotmarketing.exception.DotDataException; +import org.elasticsearch.common.unit.ByteSizeValue; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Collect the total size in Mb of all the Site Search indices. + */ +public class TotalSizeSiteSearchIndicesMetricType extends IndicesSiteSearchMetricType { + + + @Override + public String getName() { + return "TOTAL_INDICES_SIZE"; + } + + @Override + public String getDescription() { + return "Total size of indexes"; + } + + @Override + public Optional getValue(Collection indices) throws DotDataException { + return Optional.of(new ByteSizeValue( + indices.stream().collect(Collectors.summingLong(IndexStats::getSizeRaw))).toString() + ); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalAdvancedTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalAdvancedTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..b7dc05dbf2fc --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalAdvancedTemplatesDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.template; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of advanced templates + */ +public class TotalAdvancedTemplatesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_ADVANCED_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Total count of advanced templates"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT template.identifier) as value " + + "FROM template INNER JOIN template_version_info on template.identifier = template_version_info.identifier " + + "WHERE drawed = false and deleted = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalBuilderTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalBuilderTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..ae0bd90a6130 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalBuilderTemplatesDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.template; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of builder templates, it means excluding File, Advanced, and Layout templates + */ +public class TotalBuilderTemplatesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_TEMPLATE_BUILDER_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Total count of Builder templates, excluding File, Advanced, and Layout templates"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT template.identifier) as value " + + "FROM template INNER JOIN template_version_info on template.identifier = template_version_info.identifier " + + "WHERE drawed = true AND deleted = false AND title NOT LIKE 'anonymous_layout_%'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesDatabaseMetricType.java new file mode 100644 index 000000000000..d98fa0d343ef --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesDatabaseMetricType.java @@ -0,0 +1,47 @@ +package com.dotcms.telemetry.collectors.template; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of templates + */ +public class TotalTemplatesDatabaseMetricType implements DBMetricType { + + @Override + public String getName() { + return "COUNT_OF_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Total count of templates"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT template.count + file_template.count as value " + + "FROM (SELECT COUNT(DISTINCT template.identifier)" + + "FROM template_version_info " + + "INNER JOIN template ON template_version_info.identifier = template.identifier " + + "WHERE title NOT LIKE 'anonymous_layout_%' and deleted = false) template, " + + "(SELECT COUNT(DISTINCT cvi.identifier) " + + "FROM contentlet_version_info cvi, identifier id " + + "WHERE id.parent_path like '/application/templates%' and " + + "id.asset_name = 'properties.vtl' and " + + "cvi.identifier = id.id and " + + "cvi.deleted = false) as file_template"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInLivePagesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInLivePagesDatabaseMetricType.java new file mode 100644 index 000000000000..5e1712e76a36 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInLivePagesDatabaseMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.template; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total all templates used in LIVE pages + */ +public class TotalTemplatesInLivePagesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_TEMPLATES_USED_IN_LIVE_PAGES"; + } + + @Override + public String getDescription() { + return "Count of all templates used in LIVE pages"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT count(distinct contentlet.contentlet_as_json->'fields'->'template'->'value') as value " + + "FROM contentlet INNER JOIN contentlet_version_info ON contentlet_version_info.identifier = contentlet.identifier " + + "WHERE contentlet_version_info.live_inode is not null AND " + + "deleted = false AND structure_inode in (SELECT inode FROM structure WHERE name = 'Page')"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInWorkingPagesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInWorkingPagesDatabaseMetricType.java new file mode 100644 index 000000000000..968a967a1944 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/template/TotalTemplatesInWorkingPagesDatabaseMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.template; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total all templates used in Working pages + */ +public class TotalTemplatesInWorkingPagesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_OF_TEMPLATES_USED_IN_WORKING_PAGES"; + } + + @Override + public String getDescription() { + return "Count of all templates used in WORKING pages"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT count(distinct contentlet.contentlet_as_json->'fields'->'template'->'value') as value " + + "FROM contentlet INNER JOIN contentlet_version_info ON contentlet_version_info.identifier = contentlet.identifier " + + "WHERE contentlet_version_info.live_inode is null AND " + + "deleted = false AND structure_inode in (SELECT inode FROM structure WHERE name = 'Page')"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalFilesInThemeMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalFilesInThemeMetricType.java new file mode 100644 index 000000000000..381958e7fff5 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalFilesInThemeMetricType.java @@ -0,0 +1,41 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; +import com.dotmarketing.util.Logger; + +/** + * Collects the total of Number of LIVE/WORKING files in themes + */ +public class TotalFilesInThemeMetricType implements DBMetricType { + @Override + public String getName() { + return "TOTAL_FILES_IN_THEMES"; + } + + @Override + public String getDescription() { + return "Count of Number of WORKING and LIVE files in themes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct CONCAT(id.parent_path, asset_name)) as value " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE deleted = false AND " + + "id.parent_path LIKE ANY (SELECT CONCAT(id.parent_path, '%') " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path LIKE '/application/themes/%' AND id.asset_name = 'template.vtl')"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveContainerDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveContainerDatabaseMetricType.java new file mode 100644 index 000000000000..6db9ab7248fb --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveContainerDatabaseMetricType.java @@ -0,0 +1,42 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of Live containers + */ +public class TotalLiveContainerDatabaseMetricType implements DBMetricType { + + @Override + public String getName() { + return "COUNT_OF_LIVE_CONTAINERS"; + } + + @Override + public String getDescription() { + return "Total count of LIVE containers"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT container.count + file_container.count as value " + + "FROM (SELECT COUNT(DISTINCT cvi.identifier) FROM container_version_info cvi WHERE deleted = false AND live_inode is not null) container, " + + "(SELECT COUNT(DISTINCT cvi.identifier) " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path like '/application/containers%' and " + + "id.asset_name = 'container.vtl' and cvi.deleted = false AND live_inode is not null) as file_container"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveFilesInThemeMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveFilesInThemeMetricType.java new file mode 100644 index 000000000000..d553dcd8605a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalLiveFilesInThemeMetricType.java @@ -0,0 +1,41 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total of Number of LIVE files in themes + */ +public class TotalLiveFilesInThemeMetricType implements DBMetricType { + @Override + public String getName() { + return "TOTAL_LIVE_FILES_IN_THEMES"; + } + + @Override + public String getDescription() { + return "Count of Number of LIVE files in themes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct CONCAT(id.parent_path, asset_name)) as value " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE cvi.live_inode IS NOT NULL AND deleted = false AND " + + "id.parent_path LIKE ANY (SELECT CONCAT(id.parent_path, '%') " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path LIKE '/application/themes/%' AND id.asset_name = 'template.vtl')"; + + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeMetricType.java new file mode 100644 index 000000000000..2fa6ca1885f3 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total of themes + */ +public class TotalThemeMetricType implements DBMetricType { + @Override + public String getName() { + return "TOTAL_THEMES"; + } + + @Override + public String getDescription() { + return "Count of themes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(id.parent_path) as value " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path LIKE '/application/themes/%' AND id.asset_name = 'template.vtl' " + + "AND deleted = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInLiveTemplatesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInLiveTemplatesMetricType.java new file mode 100644 index 000000000000..273ce64f495a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInLiveTemplatesMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of themes used by LIVE templates + */ +public class TotalThemeUsedInLiveTemplatesMetricType implements DBMetricType { + @Override + public String getName() { + return "TOTAL_USED_THEMES_IN_LIVE_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Count of themes used by templates"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT count(distinct folder.identifier) value FROM folder " + + "WHERE inode in ( " + + "SELECT DISTINCT theme FROM template INNER JOIN template_version_info ON template_version_info.live_inode = template.inode " + + "WHERE title NOT LIKE 'anonymous_layout_%' AND deleted = false)"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInWorkingTemplatesMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInWorkingTemplatesMetricType.java new file mode 100644 index 000000000000..250e19fb0cca --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalThemeUsedInWorkingTemplatesMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of themes used by WORKING templates + */ +public class TotalThemeUsedInWorkingTemplatesMetricType implements DBMetricType { + @Override + public String getName() { + return "TOTAL_USED_THEMES_IN_WORKING_TEMPLATES"; + } + + @Override + public String getDescription() { + return "Count of themes used by templates"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT count(distinct folder.identifier) value FROM folder " + + "WHERE inode in ( " + + "SELECT DISTINCT theme FROM template INNER JOIN template_version_info ON template_version_info.working_inode = template.inode " + + "WHERE title NOT LIKE 'anonymous_layout_%' AND deleted = false and template_version_info.live_inode is null)"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalWorkingContainerDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalWorkingContainerDatabaseMetricType.java new file mode 100644 index 000000000000..c54d5a0cfc28 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/theme/TotalWorkingContainerDatabaseMetricType.java @@ -0,0 +1,42 @@ +package com.dotcms.telemetry.collectors.theme; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the total count of Working containers + */ +public class TotalWorkingContainerDatabaseMetricType implements DBMetricType { + + @Override + public String getName() { + return "COUNT_OF_WORKING_CONTAINERS"; + } + + @Override + public String getDescription() { + return "Total count of WORKING containers"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.LAYOUT; + } + + @Override + public String getSqlQuery() { + return "SELECT container.count + file_container.count as value " + + "FROM (SELECT COUNT(DISTINCT cvi.identifier) FROM container_version_info cvi WHERE deleted = false AND live_inode is null) container, " + + "(SELECT COUNT(DISTINCT cvi.identifier) " + + "FROM contentlet_version_info cvi INNER JOIN identifier id ON cvi.identifier = id.id " + + "WHERE id.parent_path like '/application/containers%' and " + + "id.asset_name = 'container.vtl' and cvi.deleted = false AND live_inode is null) as file_container"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/ContentTypesWithUrlMapDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/ContentTypesWithUrlMapDatabaseMetricType.java new file mode 100644 index 000000000000..e89203819e57 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/ContentTypesWithUrlMapDatabaseMetricType.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.urlmap; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collects the count of content types with a non-null detail page. + */ +public class ContentTypesWithUrlMapDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "CONTENT_TYPES_WITH_URL_MAP"; + } + + @Override + public String getDescription() { + return "Count of content types with URL maps"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.URL_MAPS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(*) AS value " + + "FROM structure WHERE url_map_pattern IS NOT null AND page_detail IS NOT null"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/LiveContentInUrlMapDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/LiveContentInUrlMapDatabaseMetricType.java new file mode 100644 index 000000000000..865889a32503 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/LiveContentInUrlMapDatabaseMetricType.java @@ -0,0 +1,40 @@ +package com.dotcms.telemetry.collectors.urlmap; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of all the Contentlets in content types with URL maps that have LIVE Version + */ +public class LiveContentInUrlMapDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "LIVE_CONTENTLETS_IN_CONTENT_TYPES_WITH_URL_MAP"; + } + + @Override + public String getDescription() { + return "Count of Live Contentlets in content types with URL maps"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.URL_MAPS; + } + + @Override + public String getSqlQuery() { + return "SELECT count(DISTINCT contentlet.identifier) AS value FROM contentlet " + + "INNER JOIN contentlet_version_info ON contentlet.identifier = contentlet_version_info.identifier " + + "INNER JOIN structure ON contentlet.structure_inode = structure.inode " + + "WHERE url_map_pattern IS NOT null AND page_detail IS NOT null AND deleted = false " + + "AND live_inode IS NOT null"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/UrlMapPatterWithTwoVariablesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/UrlMapPatterWithTwoVariablesDatabaseMetricType.java new file mode 100644 index 000000000000..eb64c713050b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/UrlMapPatterWithTwoVariablesDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.urlmap; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Content Types that are using a detail page with 2 or more variables. + */ +public class UrlMapPatterWithTwoVariablesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "COUNT_URL_MAP_PATTER_WITH_MORE_THAT_ONE_VARIABLE"; + } + + @Override + public String getDescription() { + return "Count of URL Map Patterns with more than one variable"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.URL_MAPS; + } + + @Override + public String getSqlQuery() { + return "SELECT count(*) AS value FROM structure " + + "WHERE page_detail IS NOT null AND REGEXP_COUNT(url_map_pattern, '\\{[^}]*\\}') >= 2"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/WorkingContentInUrlMapDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/WorkingContentInUrlMapDatabaseMetricType.java new file mode 100644 index 000000000000..943412b6a374 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/urlmap/WorkingContentInUrlMapDatabaseMetricType.java @@ -0,0 +1,40 @@ +package com.dotcms.telemetry.collectors.urlmap; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of all the Contentlets in content types with URL maps that does not have LIVE Version + */ +public class WorkingContentInUrlMapDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "WORKING_CONTENTLETS_IN_CONTENT_TYPES_WITH_URL_MAP"; + } + + @Override + public String getDescription() { + return "Count of Working Contentlets in content types with URL maps"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.URL_MAPS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(DISTINCT contentlet.identifier) as value FROM contentlet\n" + + "INNER JOIN contentlet_version_info ON contentlet.identifier = contentlet_version_info.identifier\n" + + "INNER JOIN structure ON contentlet.structure_inode = structure.inode\n" + + "WHERE url_map_pattern IS NOT null AND page_detail is not null AND deleted = false " + + "AND live_inode IS null AND working_inode is not null"; + } +} + diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/ActiveUsersDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/ActiveUsersDatabaseMetricType.java new file mode 100644 index 000000000000..88baca8d65f5 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/ActiveUsersDatabaseMetricType.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.user; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; + +/** + * Collect the count of Active User + */ +public class ActiveUsersDatabaseMetricType implements UsersDatabaseMetricType { + + @Override + public String getName() { + return "ACTIVE_USERS_COUNT"; + } + + @Override + public String getDescription() { + return "Count of Active Users"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.USERS; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(userid) as value FROM user_ " + + "WHERE " + USER_EXCLUDE + " AND lastlogindate > now() - interval '1 month'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginDatabaseMetricType.java new file mode 100644 index 000000000000..2b47bcf6e164 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginDatabaseMetricType.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.user; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; + +/** + * Collects the date of the last login. + */ +public class LastLoginDatabaseMetricType implements UsersDatabaseMetricType { + + @Override + public String getName() { + return "LAST_LOGIN"; + } + + @Override + public String getDescription() { + return "Date of the last Login"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.USERS; + } + + @Override + public String getSqlQuery() { + return "SELECT to_char (lastlogindate,'HH12:MI:SS DD Mon YYYY') AS value " + + "FROM user_ where " + USER_EXCLUDE + " ORDER BY lastlogindate DESC LIMIT 1"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginUserDatabaseMetric.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginUserDatabaseMetric.java new file mode 100644 index 000000000000..16ff1c31a01a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/LastLoginUserDatabaseMetric.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.user; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; + +/** + * Email address of the last logged-in user + */ +public class LastLoginUserDatabaseMetric implements UsersDatabaseMetricType { + + @Override + public String getName() { + return "LAST_LOGIN_USER"; + } + + @Override + public String getDescription() { + return "Email address of the Last login User"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.USERS; + } + + @Override + public String getSqlQuery() { + return "SELECT emailaddress AS value " + + "FROM user_ where " + USER_EXCLUDE + " ORDER BY lastlogindate DESC LIMIT 1"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/UsersDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/UsersDatabaseMetricType.java new file mode 100644 index 000000000000..ff06bed49cac --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/user/UsersDatabaseMetricType.java @@ -0,0 +1,15 @@ +package com.dotcms.telemetry.collectors.user; + +import com.dotcms.telemetry.MetricType; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Represents the MetaData of a User Metric that we want to collect from DataBase + * + * @see MetricType + */ +public interface UsersDatabaseMetricType extends DBMetricType { + + String USER_EXCLUDE="companyid<>'default' and userid<> 'system' and userid <> 'anonymous'"; + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ActionsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ActionsDatabaseMetricType.java new file mode 100644 index 000000000000..b63afc301cdb --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ActionsDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Workflow Actions + */ +public class ActionsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "ACTIONS_COUNT"; + } + + @Override + public String getDescription() { + return "Count of workflow actions in all schemes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(*) AS value FROM workflow_action " + + "INNER JOIN workflow_scheme ON workflow_scheme.id=workflow_action.scheme_id " + + "WHERE archived = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ContentTypesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ContentTypesDatabaseMetricType.java new file mode 100644 index 000000000000..58205f056eb0 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/ContentTypesDatabaseMetricType.java @@ -0,0 +1,38 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Content Types that are NOT using 'System Workflow' + */ +public class ContentTypesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "CONTENT_TYPES_ASSIGNED"; + } + + @Override + public String getDescription() { + return "Count content types assigned schemes other than System Workflow"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct structure_id) AS value FROM workflow_scheme_x_structure " + + "INNER JOIN workflow_scheme ON workflow_scheme.id=workflow_scheme_x_structure.scheme_id " + + "WHERE name != 'System Workflow'"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SchemesDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SchemesDatabaseMetricType.java new file mode 100644 index 000000000000..3052ce19ad91 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SchemesDatabaseMetricType.java @@ -0,0 +1,36 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + + +/** + * Collect the count of Workflow Schemes + */ +public class SchemesDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "SCHEMES_COUNT"; + } + + @Override + public String getDescription() { + return "Count of workflow schemes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + @Override + public String getSqlQuery() { + return "SELECT count(*) as value FROM workflow_scheme WHERE archived=false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/StepsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/StepsDatabaseMetricType.java new file mode 100644 index 000000000000..1497a3003083 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/StepsDatabaseMetricType.java @@ -0,0 +1,37 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + +/** + * Collect the count of Workflow Steps + */ +public class StepsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "STEPS_COUNT"; + } + + @Override + public String getDescription() { + return "Count of steps in all schemes"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(*) AS value FROM workflow_step " + + "INNER JOIN workflow_scheme ON workflow_scheme.id=workflow_step.scheme_id " + + "WHERE archived = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SubActionsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SubActionsDatabaseMetricType.java new file mode 100644 index 000000000000..d28a25720d9a --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/SubActionsDatabaseMetricType.java @@ -0,0 +1,41 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + + +/** + * Collect the count of Workflow SubActions, no matter if the same Sub Action is use for more than one Action + * in this case it count several times. + */ +public class SubActionsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "SUBACTIONS_COUNT"; + } + + @Override + public String getDescription() { + return "Count of workflow subactions in all Workflow actions"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(*) AS value " + + "FROM workflow_action_class " + + "INNER JOIN workflow_action ON workflow_action.id=workflow_action_class.action_id " + + "INNER JOIN workflow_scheme ON workflow_scheme.id=workflow_action.scheme_id " + + "WHERE archived = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/UniqueSubActionsDatabaseMetricType.java b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/UniqueSubActionsDatabaseMetricType.java new file mode 100644 index 000000000000..8d36a1dcf15b --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/collectors/workflow/UniqueSubActionsDatabaseMetricType.java @@ -0,0 +1,41 @@ +package com.dotcms.telemetry.collectors.workflow; + +import com.dotcms.telemetry.MetricCategory; +import com.dotcms.telemetry.MetricFeature; +import com.dotcms.telemetry.collectors.DBMetricType; + + +/** + * Collect the count of Unique Workflow SubActions, it means if the same Sub Action is use by several + * Workflow Action then it count as 1 + */ +public class UniqueSubActionsDatabaseMetricType implements DBMetricType { + @Override + public String getName() { + return "UNIQUE_SUBACTIONS_COUNT"; + } + + @Override + public String getDescription() { + return "Count of unique workflow subactions in all Workflow actions"; + } + + @Override + public MetricCategory getCategory() { + return MetricCategory.DIFFERENTIATING_FEATURES; + } + + @Override + public MetricFeature getFeature() { + return MetricFeature.WORKFLOW; + } + + @Override + public String getSqlQuery() { + return "SELECT COUNT(distinct workflow_action_class.name) AS value " + + "FROM workflow_action_class " + + "INNER JOIN workflow_action ON workflow_action.id=workflow_action_class.action_id " + + "INNER JOIN workflow_scheme ON workflow_scheme.id=workflow_action.scheme_id " + + "WHERE archived = false"; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/job/MetricsStatsJob.java b/dotCMS/src/main/java/com/dotcms/telemetry/job/MetricsStatsJob.java new file mode 100644 index 000000000000..ee726513c68c --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/job/MetricsStatsJob.java @@ -0,0 +1,48 @@ +package com.dotcms.telemetry.job; + +import com.dotcms.concurrent.lock.ClusterLockManager; +import com.dotcms.exception.ExceptionUtil; +import com.dotcms.telemetry.MetricsSnapshot; +import com.dotcms.telemetry.business.MetricsAPI; +import com.dotcms.telemetry.collectors.MetricStatsCollector; +import com.dotmarketing.util.Config; +import com.dotmarketing.util.Logger; +import io.vavr.Lazy; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.StatefulJob; + +/** + * Stateful job used to collect and persist a snapshot of the Metrics stats. Frequency set to once a + * day. + */ +public class MetricsStatsJob implements StatefulJob { + + public static final String JOB_NAME = "MetricsStatsJob"; + public static final String JOB_GROUP = "MetricsStatsJobGroup"; + public static final String ENABLED_PROP = "TELEMETRY_SAVE_SCHEDULE_JOB_ENABLED"; + public static final String CRON_EXPR_PROP = "TELEMETRY_SAVE_SCHEDULE"; + private static final String CRON_EXPRESSION_DEFAULT = "0 0 22 * * ?"; + + public static final Lazy ENABLED = + Lazy.of(() -> Config.getBooleanProperty(ENABLED_PROP, true)); + public static final Lazy CRON_EXPRESSION = + Lazy.of(() -> Config.getStringProperty(CRON_EXPR_PROP, CRON_EXPRESSION_DEFAULT)); + + @Override + public void execute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { + final MetricsSnapshot metricsSnapshot; + try { + metricsSnapshot = MetricStatsCollector.getStatsAndCleanUp(); + MetricsAPI.INSTANCE.persistMetricsSnapshot(metricsSnapshot); + } catch (final Throwable e) { + Logger.debug(this, String.format("Error occurred during job execution: %s", + ExceptionUtil.getErrorMessage(e)), e); + } + } + + public void run(ClusterLockManager lockManager) { + + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/osgi/Activator.java b/dotCMS/src/main/java/com/dotcms/telemetry/osgi/Activator.java new file mode 100644 index 000000000000..397501ce346e --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/osgi/Activator.java @@ -0,0 +1,111 @@ +package com.dotcms.telemetry.osgi; + +import com.dotcms.concurrent.DotConcurrentFactory; +import com.dotcms.concurrent.lock.ClusterLockManager; +import com.dotcms.telemetry.rest.TelemetryResource; +import com.dotcms.telemetry.collectors.api.ApiMetricAPI; +import com.dotcms.telemetry.collectors.api.ApiMetricFactorySubmitter; +import com.dotcms.telemetry.collectors.api.ApiMetricWebInterceptor; +import com.dotcms.telemetry.job.MetricsStatsJob; +import com.dotcms.filters.interceptor.FilterWebInterceptorProvider; +import com.dotcms.filters.interceptor.WebInterceptor; +import com.dotcms.filters.interceptor.WebInterceptorDelegate; +import com.dotcms.rest.config.RestServiceUtil; +import com.dotmarketing.filters.InterceptorFilter; +import com.dotmarketing.osgi.GenericBundleActivator; +import com.dotmarketing.util.Config; +import com.dotmarketing.util.Logger; +import io.vavr.Lazy; +import org.apache.logging.log4j.core.util.CronExpression; +import org.osgi.framework.BundleContext; + +import java.text.ParseException; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class Activator extends GenericBundleActivator { + public static String version; + + private final WebInterceptorDelegate delegate = FilterWebInterceptorProvider + .getInstance(Config.CONTEXT) + .getDelegate(InterceptorFilter.class); + + private final WebInterceptor apiCallWebInterceptor = new ApiMetricWebInterceptor(); + private final MetricsStatsJob metricsStatsJob = new MetricsStatsJob(); + + private static final String METRICS_JOB_LOCK_KEY = "metrics_job_lock"; + private ScheduledFuture scheduledFuture; + private final Lazy enableTelemetry = Lazy.of(() -> + Config.getBooleanProperty("FEATURE_FLAG_TELEMETRY", false)); + + private final Lazy enableAPIMetrics = Lazy.of(() -> + Config.getBooleanProperty("TELEMETRY_API_METRICS_ENABLED", false)); + + public static final ApiMetricAPI apiStatAPI = new ApiMetricAPI(); + + @Override + public void start(final BundleContext context) { + + PluginVersionUtil.init(context); + + if(Boolean.TRUE.equals(enableTelemetry.get())) { + Logger.debug(Activator.class.getName(), "Starting the Telemetry plugin"); + + RestServiceUtil.addResource(TelemetryResource.class); + + try { + apiStatAPI.dropTemporaryTable(); + apiStatAPI.createTemporaryTable(); + + if(Boolean.TRUE.equals(enableAPIMetrics.get())) { + Logger.debug(Activator.class.getName(), "API metrics enabled"); + delegate.addFirst(apiCallWebInterceptor); + ApiMetricFactorySubmitter.INSTANCE.start(); + } + Logger.debug(Activator.class.getName(), "Scheduling Telemetry Job"); + scheduleMetricsJob(); + Logger.debug(Activator.class.getName(), "The Telemetry plugin was started"); + } catch (Throwable t) { + Logger.debug(this, "Error starting the Telemetry plugin.", t); + } + } + } + + private void scheduleMetricsJob() throws ParseException { + final ClusterLockManager lockManager = DotConcurrentFactory.getInstance() + .getClusterLockManager(METRICS_JOB_LOCK_KEY); + + CronExpression cron = new CronExpression(Config + .getStringProperty("TELEMETRY_SAVE_SCHEDULE", "0 0 22 * * ?")) ; + + final Instant now = Instant.now(); + final Instant previousRun = cron.getPrevFireTime(Date.from(now)).toInstant(); + final Instant nextRun = cron.getNextValidTimeAfter(Date.from(previousRun)).toInstant(); + final Duration delay = Duration.between(now, nextRun); + final Duration runEvery = Duration.between(previousRun, nextRun); + + scheduledFuture = DotConcurrentFactory.getScheduledThreadPoolExecutor().scheduleAtFixedRate( + () -> metricsStatsJob.run(lockManager) + , delay.get(ChronoUnit.SECONDS), + runEvery.get(ChronoUnit.SECONDS), + TimeUnit.SECONDS); + } + + @Override + public void stop(BundleContext context) throws Exception { + if(Boolean.TRUE.equals(enableTelemetry.get())) { + RestServiceUtil.removeResource(TelemetryResource.class); + scheduledFuture.cancel(false); + apiStatAPI.dropTemporaryTable(); + + if(Boolean.TRUE.equals(enableAPIMetrics.get())) { + delegate.remove(apiCallWebInterceptor.getName(), true); + ApiMetricFactorySubmitter.INSTANCE.shutdownNow(); + } + } + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/osgi/PluginVersionUtil.java b/dotCMS/src/main/java/com/dotcms/telemetry/osgi/PluginVersionUtil.java new file mode 100644 index 000000000000..15173b777101 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/osgi/PluginVersionUtil.java @@ -0,0 +1,18 @@ +package com.dotcms.telemetry.osgi; + +import org.osgi.framework.BundleContext; + +public class PluginVersionUtil { + + private static String version; + + private PluginVersionUtil(){} + + public static void init(BundleContext context) { + version = context.getBundle().getHeaders().get("Bundle-Version"); + } + + public static String getVersion(){ + return version; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/rest/ResponseEntityMetricsSnapshotView.java b/dotCMS/src/main/java/com/dotcms/telemetry/rest/ResponseEntityMetricsSnapshotView.java new file mode 100644 index 000000000000..6a1c77b9ac44 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/rest/ResponseEntityMetricsSnapshotView.java @@ -0,0 +1,14 @@ +package com.dotcms.telemetry.rest; + +import com.dotcms.telemetry.MetricsSnapshot; +import com.dotcms.rest.ResponseEntityView; + +/** + * {@link ResponseEntityView} of {@link MetricsSnapshot} + */ +public class ResponseEntityMetricsSnapshotView extends ResponseEntityView { + + public ResponseEntityMetricsSnapshotView(final MetricsSnapshot entity) { + super(entity); + } +} \ No newline at end of file diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/rest/TelemetryResource.java b/dotCMS/src/main/java/com/dotcms/telemetry/rest/TelemetryResource.java new file mode 100644 index 000000000000..cb50f24c37fa --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/rest/TelemetryResource.java @@ -0,0 +1,51 @@ +package com.dotcms.telemetry.rest; + +import com.dotcms.telemetry.collectors.MetricStatsCollector; +import com.dotcms.rest.WebResource; +import com.dotcms.rest.annotation.NoCache; +import com.dotmarketing.business.Role; +import com.dotmarketing.util.Logger; +import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("/v1/telemetry") +public class TelemetryResource { + + @Path("/stats") + @GET + @JSONP + @NoCache + @Produces({MediaType.APPLICATION_JSON}) + @Operation(summary = "Retrieves dotCMS usage data", + responses = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = + ResponseEntityMetricsSnapshotView.class)))}) + public final Response getData(@Context final HttpServletRequest request, + @Context final HttpServletResponse response) { + new WebResource.InitBuilder(new WebResource()) + .requestAndResponse(request, response) + .requiredBackendUser(true) + .rejectWhenNoUser(true) + .requiredRoles(Role.CMS_ADMINISTRATOR_ROLE) + .init(); + + return Response.ok(new ResponseEntityMetricsSnapshotView(MetricStatsCollector.getStats())) + .build(); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/util/IndicesSiteSearchUtil.java b/dotCMS/src/main/java/com/dotcms/telemetry/util/IndicesSiteSearchUtil.java new file mode 100644 index 000000000000..b297ad179ba4 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/util/IndicesSiteSearchUtil.java @@ -0,0 +1,30 @@ +package com.dotcms.telemetry.util; + +import com.dotcms.content.elasticsearch.business.IndexStats; +import com.dotcms.content.elasticsearch.business.IndexType; +import com.dotmarketing.business.APILocator; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Provide util methods to get data from the SiteSearch Indices + */ +public enum IndicesSiteSearchUtil { + + INSTANCE; + + /** + * Return all the Site Search Index Information. + * + * @return + */ + public Collection getESIndices() { + return APILocator.getESIndexAPI().getIndicesStats().entrySet().stream() + .map(Map.Entry::getValue) + .filter(index -> IndexType.SITE_SEARCH.is(index.getIndexName())) + .collect(Collectors.toList()); + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/util/JsonUtil.java b/dotCMS/src/main/java/com/dotcms/telemetry/util/JsonUtil.java new file mode 100644 index 000000000000..8583bb691b56 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/util/JsonUtil.java @@ -0,0 +1,24 @@ +package com.dotcms.telemetry.util; + +import com.dotcms.telemetry.business.MetricEndpointPayload; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.json.JsonMapper; + +/** + * Util class to handle Json format + */ +public enum JsonUtil { + + INSTANCE; + + static final JsonMapper jsonMapper = new JsonMapper(); + + public String getAsJson(final MetricEndpointPayload metricEndpointPayload) { + try { + return jsonMapper.writeValueAsString(metricEndpointPayload); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCache.java b/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCache.java new file mode 100644 index 000000000000..f52f7d25975f --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCache.java @@ -0,0 +1,33 @@ +package com.dotcms.telemetry.util; + + +import java.util.function.Supplier; + +/** + * This is a cache designed to store any results needed by multiple instances of + * {@link com.dotcms.telemetry.MetricType}. You can utilize a supplier to obtain the data you wish + * to store. The cache is flushed every 10 minutes. + * + * @param + */ +public class MetricCache { + + private final Supplier supplier; + private T currentValue = null; + + public MetricCache(final Supplier supplier) { + this.supplier = supplier; + } + + public T get() { + if (currentValue == null) { + currentValue = this.supplier.get(); + } + + return currentValue; + } + + public void flush() { + currentValue = null; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCaches.java b/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCaches.java new file mode 100644 index 000000000000..4044048424e9 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/telemetry/util/MetricCaches.java @@ -0,0 +1,33 @@ +package com.dotcms.telemetry.util; + +import com.dotcms.telemetry.collectors.api.ApiMetricAPI; + +import java.util.Arrays; + +/** + * Collection of all the Cache regions used on the Telemetry feature + */ +public enum MetricCaches { + + SITE_SEARCH_INDICES(new MetricCache<>(IndicesSiteSearchUtil.INSTANCE::getESIndices)), + TEMPORARY_TABLA_DATA(new MetricCache<>(ApiMetricAPI::getMetricTemporaryTableData)); + + private final MetricCache metricCache; + + MetricCaches(final MetricCache metricCache) { + this.metricCache = metricCache; + } + + public static void flushAll() { + Arrays.stream(MetricCaches.values()).parallel().forEach(metricCaches -> metricCaches.cache().flush()); + } + + public T get() { + return (T) metricCache.get(); + } + + public MetricCache cache() { + return metricCache; + } + +} From a27c77d0bfee1b8279002bb86cdbb51cb79d3d07 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 31 Oct 2024 13:07:36 -0600 Subject: [PATCH 05/11] #30519 adding history and comments (#30527) Adding the workflow task history and comments for edit contenlet --- ...onseEntityWorkflowHistoryCommentsView.java | 16 ++ .../api/v1/workflow/WorkflowResource.java | 104 ++++++++ .../v1/workflow/WorkflowTimelineItemView.java | 56 ++++ .../workflow/helper/WorkflowHelper.java | 23 ++ .../postman/Workflow_Resource_Tests.json | 246 +++++++++++++++++- 5 files changed, 444 insertions(+), 1 deletion(-) create mode 100644 dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowHistoryCommentsView.java create mode 100644 dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowTimelineItemView.java diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowHistoryCommentsView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowHistoryCommentsView.java new file mode 100644 index 000000000000..92c17693fac1 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowHistoryCommentsView.java @@ -0,0 +1,16 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.model.WorkflowTimelineItem; + +import java.util.List; + +/** + * This class is used to return a list of WorkflowTimelineItem objects as a response entity. + */ +public class ResponseEntityWorkflowHistoryCommentsView extends ResponseEntityView> { + + public ResponseEntityWorkflowHistoryCommentsView(final List entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java index 478f461f2e0f..6af7b36b561b 100644 --- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java @@ -73,9 +73,11 @@ import com.dotmarketing.portlets.workflows.model.SystemActionWorkflowActionMapping; import com.dotmarketing.portlets.workflows.model.WorkflowAction; import com.dotmarketing.portlets.workflows.model.WorkflowActionClass; +import com.dotmarketing.portlets.workflows.model.WorkflowComment; import com.dotmarketing.portlets.workflows.model.WorkflowScheme; import com.dotmarketing.portlets.workflows.model.WorkflowStep; import com.dotmarketing.portlets.workflows.model.WorkflowTask; +import com.dotmarketing.portlets.workflows.model.WorkflowTimelineItem; import com.dotmarketing.portlets.workflows.util.WorkflowImportExportUtil; import com.dotmarketing.portlets.workflows.util.WorkflowSchemeImportExportObject; import com.dotmarketing.util.Config; @@ -140,6 +142,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -5596,4 +5599,105 @@ public final ResponseContentletWorkflowStatusView getStatusForContentlet(@Contex wfStep, wfTask)); } + /** + * Returns the status of a specific piece of Content in the Workflow it is assigned to. In + * summary: + *
    + *
  • The Workflow Scheme that the Contentlet is in.
  • + *
  • The Step that the Contentlet is in.
  • + *
  • The User assigned to such a Step.
  • + *
+ * Here's an example of how to use this endpoint: + *
+     *     http://localhost:8080/api/v1/workflow/status/{contentletInode}
+     * 
+ * + * @param request The current instance of the {@link HttpServletRequest}. + * @param response The current instance of the {@link HttpServletResponse}. + * @param contentletIdentifier The inode of the Contentlet whose status will be checked. + * + * @return The status information of the Contentlet in the Workflow it is assigned to. + * + * @throws DotDataException The specified Contentlet Inode was not found. + * @throws DotSecurityException The User calling this endpoint does not have required + * permissions to do so. + * @throws InvocationTargetException Failed to transform the {@link WorkflowTask} data for this + * view. + * @throws IllegalAccessException Failed to transform the {@link WorkflowTask} data for this + * view. + */ + @GET + @Path("/tasks/history/comments/{contentletIdentifier}") + @JSONP + @NoCache + @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowTasksHistoryComments", summary = "Find workflow tasks history and comments of content", + description = "Retrieve the workflow tasks comments of a contentlet by its [id]" + + "(https://www.dotcms.com/docs/latest/content-versions#IdentifiersInodes).\n\n" + + "Returns an object containing the associated [workflow history or comments]" + + "https://www2.dotcms.com/docs/latest/workflow-tasks, [workflow task]", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Action(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowHistoryCommentsView.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad Requesy"), + @ApiResponse(responseCode = "401", description = "Invalid User"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") // includes when inode not found + } + ) + public final ResponseEntityWorkflowHistoryCommentsView getWorkflowTasksHistoryComments(@Context final HttpServletRequest request, + @Context final HttpServletResponse response, + @PathParam("contentletIdentifier") @Parameter( + required = true, + description = "Id of content to inspect for workflow tasks.\n\n", + schema = @Schema(type = "string") + ) final String contentletIdentifier, + @DefaultValue("-1") @QueryParam("language") @Parameter( + description = "Language version of target content.", + schema = @Schema(type = "string")) final String language + ) + throws DotDataException, DotSecurityException, InvocationTargetException, IllegalAccessException { + + Logger.debug(this, String.format("Retrieving Workflow tasks for Contentlet with identifier " + + "'%s'", contentletIdentifier)); + final InitDataObject initDataObject = new WebResource.InitBuilder(webResource) + .requestAndResponse(request, response) + .rejectWhenNoUser(true) + .requiredBackendUser(true).requiredFrontendUser(false).init(); + + final User user = initDataObject.getUser(); + final long languageId = LanguageUtil.getLanguageId(language); + final PageMode mode = PageMode.get(request); + + final Optional currentContentlet = languageId <= 0? + this.workflowHelper.getContentletByIdentifier(contentletIdentifier, mode, initDataObject.getUser(), + ()->WebAPILocator.getLanguageWebAPI().getLanguage(request).getId()): + this.contentletAPI.findContentletByIdentifierOrFallback + (contentletIdentifier, mode.showLive, languageId, initDataObject.getUser(), mode.respectAnonPerms); + + + if (currentContentlet.isPresent()) { + + final WorkflowTask currentWorkflowTask = this.workflowAPI.findTaskByContentlet(currentContentlet.get()); + final List workflowComments = this.workflowAPI.getCommentsAndChangeHistory(currentWorkflowTask); + final List workflowTimelineItemViews = workflowComments.stream() + .map(this::toWorkflowTimelineItemView) + .collect(Collectors.toList()); + return new ResponseEntityWorkflowHistoryCommentsView(workflowTimelineItemViews); + } + + throw new DoesNotExistException("Contentlet with identifier " + contentletIdentifier + " does not exist."); + } + + private WorkflowTimelineItemView toWorkflowTimelineItemView(final WorkflowTimelineItem wfTimeLine) { + + final String postedBy = this.workflowHelper.getPostedBy(wfTimeLine.roleId()); + return new WorkflowTimelineItemView(wfTimeLine.createdDate(), wfTimeLine.roleId(), postedBy, + wfTimeLine.commentDescription(), wfTimeLine.taskId(), wfTimeLine.type()); + } + } // E:O:F:WorkflowResource. diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowTimelineItemView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowTimelineItemView.java new file mode 100644 index 000000000000..b554eb31de65 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowTimelineItemView.java @@ -0,0 +1,56 @@ +package com.dotcms.rest.api.v1.workflow; + +import java.util.Date; + +/** + * This class is used to return a list of WorkflowTimelineItem objects as a response entity. + * + * @author jsanca + */ +public class WorkflowTimelineItemView { + + private final Date createdDate; + private final String roleId; + private final String postedBy; + private final String commentDescription; + private final String taskId; + private final String type; + + public WorkflowTimelineItemView(final Date createdDate, + final String roleId, + final String postedBy, + final String commentDescription, + final String taskId, + final String type) { + this.createdDate = createdDate; + this.roleId = roleId; + this.postedBy = postedBy; + this.commentDescription = commentDescription; + this.taskId = taskId; + this.type = type; + } + + public Date getCreatedDate() { + return createdDate; + } + + public String getRoleId() { + return roleId; + } + + public String getPostedBy() { + return postedBy; + } + + public String getCommentDescription() { + return commentDescription; + } + + public String getTaskId() { + return taskId; + } + + public String getType() { + return type; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/workflow/helper/WorkflowHelper.java b/dotCMS/src/main/java/com/dotcms/workflow/helper/WorkflowHelper.java index 2773376ce20a..43ed7d2b3ad1 100644 --- a/dotCMS/src/main/java/com/dotcms/workflow/helper/WorkflowHelper.java +++ b/dotCMS/src/main/java/com/dotcms/workflow/helper/WorkflowHelper.java @@ -2046,4 +2046,27 @@ public WorkflowTask handleWorkflowTaskData(final WorkflowTask wfTask) { return wfTask; } + /** + * Tries to recover the user name based on the role + * @param roleId + * @return String + */ + public String getPostedBy(final String roleId){ + + String postedBy = "unknown"; + try { + + postedBy = APILocator.getUserAPI().loadUserById(roleId, APILocator.systemUser(), false).getFullName(); + } catch (Exception e) { + try{ + postedBy = APILocator.getRoleAPI().loadRoleById(roleId).getName(); + } + catch(Exception ee){ + + } + } + return postedBy; + } + + } // E:O:F:WorkflowHelper. diff --git a/dotcms-postman/src/main/resources/postman/Workflow_Resource_Tests.json b/dotcms-postman/src/main/resources/postman/Workflow_Resource_Tests.json index 995596c60da5..65ee087d9395 100644 --- a/dotcms-postman/src/main/resources/postman/Workflow_Resource_Tests.json +++ b/dotcms-postman/src/main/resources/postman/Workflow_Resource_Tests.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "e53e1b4d-87ee-4920-9477-917bb7ad4d95", + "_postman_id": "ab29610c-81bb-4366-94c3-ed154b1e9ec9", "name": "Workflow Resource Tests [/api/v1/workflows]", "description": "Test the necesary validations to every end point of the worlflow resource ", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", @@ -17535,6 +17535,246 @@ "response": [] } ] + }, + { + "name": "Tasks", + "item": [ + { + "name": "CreateRichText", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "", + "", + "pm.collectionVariables.set(\"identifier\", jsonData.entity.identifier);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\":{\n \"contentType\":\"webPageContent\",\n \"title\":\"Test3-11\",\n \"contentHost\":\"default\",\n \"body\":\"Test body\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "CreateRichText-Again", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "", + "", + "pm.collectionVariables.set(\"identifier\", jsonData.entity.identifier);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\":{\n \"contentType\":\"webPageContent\",\n \"title\":\"Test3-11\",\n \"contentHost\":\"default\",\n \"body\":\"Test body\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR&identifier={{identifier}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + }, + { + "key": "identifier", + "value": "{{identifier}}" + } + ] + } + }, + "response": [] + }, + { + "name": "CheckHistoryAndComment", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "", + "// Test para verificar que el JSON de respuesta tiene las propiedades principales", + "pm.test(\"Response has expected properties\", function () {", + " pm.expect(jsonData).to.have.property(\"entity\");", + " pm.expect(jsonData).to.have.property(\"errors\");", + " pm.expect(jsonData).to.have.property(\"i18nMessagesMap\");", + " pm.expect(jsonData).to.have.property(\"messages\");", + " pm.expect(jsonData).to.have.property(\"pagination\");", + " pm.expect(jsonData).to.have.property(\"permissions\");", + "});", + "", + "// Test para verificar que \"entity\" es un array y tiene al menos un elemento", + "pm.test(\"Entity is an array and contains items\", function () {", + " const entity = pm.response.json().entity;", + " pm.expect(entity).to.be.an(\"array\").that.is.not.empty;", + "});", + "", + "// Test para verificar las propiedades de los objetos dentro de \"entity\"", + "pm.test(\"Each entity item has expected properties\", function () {", + " const entity = pm.response.json().entity;", + " entity.forEach(item => {", + " pm.expect(item).to.have.property(\"commentDescription\");", + " pm.expect(item).to.have.property(\"createdDate\");", + " pm.expect(item).to.have.property(\"postedBy\");", + " pm.expect(item).to.have.property(\"roleId\");", + " pm.expect(item).to.have.property(\"taskId\");", + " pm.expect(item).to.have.property(\"type\");", + " ", + " // Verificación de tipo de dato para cada propiedad", + " pm.expect(item.commentDescription).to.be.a(\"string\");", + " pm.expect(item.createdDate).to.be.a(\"number\");", + " pm.expect(item.postedBy).to.be.a(\"string\");", + " pm.expect(item.roleId).to.be.a(\"string\");", + " pm.expect(item.taskId).to.be.a(\"string\");", + " pm.expect(item.type).to.be.a(\"string\");", + " });", + "});", + "", + "// Test para verificar que no hay errores en el array \"errors\"", + "pm.test(\"Errors array is empty\", function () {", + " const errors = pm.response.json().errors;", + " pm.expect(errors).to.be.an(\"array\").that.is.empty;", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/workflow/tasks/history/comments/{{identifier}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "tasks", + "history", + "comments", + "{{identifier}}" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -17633,6 +17873,10 @@ { "key": "fireActionLanguageKey", "value": "" + }, + { + "key": "identifier", + "value": "" } ] } \ No newline at end of file From 265496ad1b92367803c542646d1124d88ad33615 Mon Sep 17 00:00:00 2001 From: Jonathan Gamba Date: Thu, 31 Oct 2024 13:17:53 -0600 Subject: [PATCH 06/11] Fix (CLI): Adding back builder to properly handle content type base types. (#30537) This pull request introduces a custom builder for `SaveContentTypeRequest` to handle the `typeInf` attribute and updates relevant tests and methods to use this new builder. The most important changes include adding the custom builder class, updating test cases, and modifying methods to utilize the new builder. ### Enhancements to `SaveContentTypeRequest`: * Added a custom `Builder` class to `AbstractSaveContentTypeRequest` to handle the `typeInf` attribute. (`tools/dotcms-cli/api-data-model/src/main/java/com/dotcms/model/contenttype/AbstractSaveContentTypeRequest.java`) ### Updates to Test Cases: * Updated imports and added new test methods in `ContentTypeAPIIT` to test the new builder functionality. (`tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java`) [[1]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6R24-R30) [[2]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6R148-R191) * Modified existing test methods to use the new `AbstractSaveContentTypeRequest.builder().of(contentType).build()` pattern. (`tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java`) [[1]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6L237-R283) [[2]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6L361-R407) [[3]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6L626-R675) [[4]](diffhunk://#diff-f2101fd155aefd1a94a63ecac9b5675e464720447b556c8b05c60c1d52648de6L952-R1001) ### Codebase Simplification: * Updated `ContentTypePushHandler` to use the new builder for creating and editing content types. (`tools/dotcms-cli/cli/src/main/java/com/dotcms/api/client/push/contenttype/ContentTypePushHandler.java`) [[1]](diffhunk://#diff-ed28cb0bb540c2c7a442107ec9cf370696bc98f1b411311b3c2817b0c78d0968R8) [[2]](diffhunk://#diff-ed28cb0bb540c2c7a442107ec9cf370696bc98f1b411311b3c2817b0c78d0968L81-R83) --- .../AbstractSaveContentTypeRequest.java | 39 ++++++ .../java/com/dotcms/api/ContentTypeAPIIT.java | 100 +++++++++++---- .../contenttype/ContentTypePushHandler.java | 9 +- .../contenttype/ContentTypeCommandIT.java | 60 +++++++++ .../common/ContentTypesTestHelperService.java | 115 +++++++++++++++++- 5 files changed, 291 insertions(+), 32 deletions(-) diff --git a/tools/dotcms-cli/api-data-model/src/main/java/com/dotcms/model/contenttype/AbstractSaveContentTypeRequest.java b/tools/dotcms-cli/api-data-model/src/main/java/com/dotcms/model/contenttype/AbstractSaveContentTypeRequest.java index 4a3b37b060f2..b8ebafe8cd06 100644 --- a/tools/dotcms-cli/api-data-model/src/main/java/com/dotcms/model/contenttype/AbstractSaveContentTypeRequest.java +++ b/tools/dotcms-cli/api-data-model/src/main/java/com/dotcms/model/contenttype/AbstractSaveContentTypeRequest.java @@ -70,4 +70,43 @@ public String idFromValue(Object value) { } + /** + * Custom Builder to handle the typeInf attribute. + */ + public static class Builder extends SaveContentTypeRequest.Builder { + + private Class typeInf = SimpleContentType.class; + + /** + * Sets the typeInf attribute based on the provided ContentType instance. + * + * @param in the ContentType instance + * @return the updated SaveContentTypeRequest.Builder + */ + public SaveContentTypeRequest.Builder of(ContentType in) { + this.typeInf = in.getClass(); + return from(in); + } + + /** + * Builds the SaveContentTypeRequest and sets the typeInf attribute. + * + * @return the built SaveContentTypeRequest + */ + @Override + public SaveContentTypeRequest build() { + this.typeInf(typeInf); + return super.build(); + } + } + + /** + * Helper method to create the custom Builder. + * + * @return a new instance of the custom Builder + */ + public static Builder builder() { + return new Builder(); + } + } diff --git a/tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java b/tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java index ceec15d90d29..84abd751b21d 100644 --- a/tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java +++ b/tools/dotcms-cli/api-data-model/src/test/java/com/dotcms/api/ContentTypeAPIIT.java @@ -21,11 +21,13 @@ import com.dotcms.contenttype.model.field.Relationships; import com.dotcms.contenttype.model.type.BaseContentType; import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.contenttype.model.type.ImmutablePageContentType; import com.dotcms.contenttype.model.type.ImmutableSimpleContentType; import com.dotcms.contenttype.model.type.SimpleContentType; import com.dotcms.contenttype.model.workflow.SystemAction; import com.dotcms.model.ResponseEntityView; import com.dotcms.model.config.ServiceBean; +import com.dotcms.model.contenttype.AbstractSaveContentTypeRequest; import com.dotcms.model.contenttype.FilterContentTypesRequest; import com.dotcms.model.contenttype.SaveContentTypeRequest; import com.dotcms.model.site.GetSiteByNameRequest; @@ -114,7 +116,6 @@ void Test_Content_Type_Model_Serialization() throws JsonProcessingException { .build()).build(); final String ctAsString = objectMapper.writeValueAsString(contentType); - System.out.println(ctAsString); final ContentType ct = objectMapper.readValue(ctAsString, ContentType.class); Assert.assertNotNull(ct); @@ -144,6 +145,50 @@ abstract class AbstractContentTypesResponse extends AbstractResponseEntityView < */ } + /** + * Generate a CT using our classes model then test we can go back and forth using serialization + * and test our fields actually get translated properly using polymorphism to finally test we + * can create a SaveContentTypeRequest from a ContentType and the values are properly set. + * + * @throws JsonProcessingException If an error occurs while processing JSON. + */ + @Test + void Test_Content_Type_Model_SaveContentTypeRequest() throws JsonProcessingException { + + final ObjectMapper objectMapper = new ClientObjectMapper().getContext(null); + + final ImmutablePageContentType contentType = ImmutablePageContentType.builder() + .baseType(BaseContentType.HTMLPAGE) + .description("desc") + .id("1") + .variable("var") + .addFields(ImmutableBinaryField.builder() + .name("name") + .id("1") + .variable("fieldVar") + .build()).build(); + + final String ctAsString = objectMapper.writeValueAsString(contentType); + + final ContentType ct = objectMapper.readValue(ctAsString, ContentType.class); + Assert.assertNotNull(ct); + Assert.assertTrue( + ct.fields().stream().anyMatch(field -> field instanceof BinaryField)); + + Assertions.assertEquals(BaseContentType.HTMLPAGE, ct.baseType()); + Assertions.assertEquals(ContentType.SYSTEM_HOST, ct.host()); + Assertions.assertEquals(ContentType.SYSTEM_FOLDER, ct.folder()); + + // Now we validate that when we create a SaveContentTypeRequest from a ContentType we have + // the proper values + final SaveContentTypeRequest contentTypeRequest = AbstractSaveContentTypeRequest.builder() + .of(ct).build(); + Assertions.assertEquals(BaseContentType.HTMLPAGE, contentTypeRequest.baseType()); + Assertions.assertEquals(ct.getClass(), contentTypeRequest.typeInf()); + Assertions.assertEquals(ContentType.SYSTEM_HOST, contentTypeRequest.host()); + Assertions.assertEquals(ContentType.SYSTEM_FOLDER, contentTypeRequest.folder()); + } + /** * Test that we can hit */ @@ -234,8 +279,8 @@ void Test_Create_Then_Update_Then_Delete_Content_Type() { ).build(); final ContentTypeAPI client = apiClientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder(). + of(contentType).build(); final ResponseEntityView> response = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(response); @@ -250,8 +295,8 @@ void Test_Create_Then_Update_Then_Delete_Content_Type() { // Now lets test update final ImmutableSimpleContentType updatedContentType = ImmutableSimpleContentType.builder().from(newContentType).description("Updated").build(); - final SaveContentTypeRequest request = SaveContentTypeRequest.builder(). - from(updatedContentType).build(); + final SaveContentTypeRequest request = AbstractSaveContentTypeRequest.builder(). + of(updatedContentType).build(); final ResponseEntityView responseEntityView = getUpdateContentTypeResponse( client, request); Assertions.assertEquals("Updated", responseEntityView.entity().description()); @@ -358,8 +403,8 @@ void Test_Create_Then_Update_Action_Mappings() throws JsonProcessingException { // --- // Create the content type with the action mappings final var contentType = contentTypeWithoutMapping.withSystemActionMappings(jsonNodeV1); - final SaveContentTypeRequest request = SaveContentTypeRequest.builder() - .from(contentType).build(); + final SaveContentTypeRequest request = AbstractSaveContentTypeRequest.builder() + .of(contentType).build(); final ResponseEntityView> createContentTypeResponse = client.createContentTypes(List.of(request)); @@ -378,8 +423,8 @@ void Test_Create_Then_Update_Action_Mappings() throws JsonProcessingException { // Modifying the content type without system mappings, nothing should change in mappings var modifiedContentType = contentTypeWithoutMapping.withDescription("Modified!"); - final SaveContentTypeRequest contentTypeRequest = SaveContentTypeRequest.builder() - .from(modifiedContentType).build(); + final SaveContentTypeRequest contentTypeRequest = AbstractSaveContentTypeRequest.builder() + .of(modifiedContentType).build(); // Use of Awaitility to wait for the modified response await().atMost(10, TimeUnit.SECONDS).until(() -> { @@ -402,7 +447,8 @@ void Test_Create_Then_Update_Action_Mappings() throws JsonProcessingException { .withDescription("Modified 2!") .withSystemActionMappings(jsonNodeV2); - final SaveContentTypeRequest contentTypeRequest1 = SaveContentTypeRequest.builder().from(modifiedContentType).build(); + final SaveContentTypeRequest contentTypeRequest1 = AbstractSaveContentTypeRequest.builder() + .of(modifiedContentType).build(); await().atMost(10, TimeUnit.SECONDS).until(() -> { ResponseEntityView updateContentTypeResponse = getUpdateContentTypeResponse( @@ -424,7 +470,8 @@ void Test_Create_Then_Update_Action_Mappings() throws JsonProcessingException { .withDescription("Modified 3!") .withSystemActionMappings(jsonNodeV3); - final SaveContentTypeRequest contentTypeRequest2 = SaveContentTypeRequest.builder().from(modifiedContentType).build(); + final SaveContentTypeRequest contentTypeRequest2 = AbstractSaveContentTypeRequest.builder() + .of(modifiedContentType).build(); await().atMost(10, TimeUnit.SECONDS).until(() -> { ResponseEntityView updateContentTypeResponse = getUpdateContentTypeResponse( @@ -443,7 +490,8 @@ void Test_Create_Then_Update_Action_Mappings() throws JsonProcessingException { .withDescription("Modified 4!") .withSystemActionMappings(jsonNodeV4); - final SaveContentTypeRequest contentTypeRequest3 = SaveContentTypeRequest.builder().from(modifiedContentType).build(); + final SaveContentTypeRequest contentTypeRequest3 = AbstractSaveContentTypeRequest.builder() + .of(modifiedContentType).build(); await().atMost(10, TimeUnit.SECONDS).until(() -> { ResponseEntityView updateContentTypeResponse = getUpdateContentTypeResponse( @@ -623,8 +671,8 @@ void Test_Send_Invalid_Host_And_Folder_Verify_Defaults() { .build() ).build(); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType1).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder(). + of(contentType1).build(); final ResponseEntityView> contentTypeResponse1 = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(contentTypeResponse1); @@ -670,8 +718,8 @@ void Test_Send_Folder_Path_Only_Valid_Folder_Expect_Matching_Folder_Id() { .build() ).build(); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType1).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder() + .of(contentType1).build(); final ResponseEntityView> contentTypeResponse2 = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(contentTypeResponse2); @@ -718,8 +766,8 @@ void Test_Create_Content_Type_Out_Of_Folder_Path() { .build() ).build(); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType2).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder(). + of(contentType2).build(); final ResponseEntityView> contentTypeResponse2 = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(contentTypeResponse2); @@ -770,8 +818,8 @@ void Test_ContentType_Without_Layout_Attribute() { final ContentTypeAPI client = apiClientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder(). + of(contentType).build(); final ResponseEntityView> contentTypeResponse = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(contentTypeResponse); @@ -865,8 +913,8 @@ void Test_ContentType_Layout_Attribute_Is_Ignored() { final ContentTypeAPI client = apiClientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder(). + of(contentType).build(); final ResponseEntityView> contentTypeResponse = client.createContentTypes(List.of(saveRequest)); Assertions.assertNotNull(contentTypeResponse); @@ -949,8 +997,8 @@ void Simple_Relationship_Support_Test() throws IOException { final ContentTypeAPI client = apiClientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveBlogRequest = SaveContentTypeRequest.builder(). - from(blog).build(); + final SaveContentTypeRequest saveBlogRequest = AbstractSaveContentTypeRequest.builder(). + of(blog).build(); final ResponseEntityView> contentTypeResponse1 = client.createContentTypes(List.of(saveBlogRequest)); ContentType savedContentType1 = null; ContentType savedContentType2 = null; @@ -973,8 +1021,8 @@ void Simple_Relationship_Support_Test() throws IOException { //Assertions.assertTrue(relationships1.isParentField()); Assertions.assertEquals("MyBlogComment" + timeMark, relationships1.velocityVar()); - final SaveContentTypeRequest saveBlogCommentRequest = SaveContentTypeRequest.builder(). - from(blogComment).build(); + final SaveContentTypeRequest saveBlogCommentRequest = AbstractSaveContentTypeRequest.builder(). + of(blogComment).build(); final ResponseEntityView> contentTypeResponse2 = client.createContentTypes( List.of(saveBlogCommentRequest)); final List contentTypes2 = contentTypeResponse2.entity(); diff --git a/tools/dotcms-cli/cli/src/main/java/com/dotcms/api/client/push/contenttype/ContentTypePushHandler.java b/tools/dotcms-cli/cli/src/main/java/com/dotcms/api/client/push/contenttype/ContentTypePushHandler.java index 34cc9defa792..a252f60f95af 100644 --- a/tools/dotcms-cli/cli/src/main/java/com/dotcms/api/client/push/contenttype/ContentTypePushHandler.java +++ b/tools/dotcms-cli/cli/src/main/java/com/dotcms/api/client/push/contenttype/ContentTypePushHandler.java @@ -5,6 +5,7 @@ import com.dotcms.api.client.push.PushHandler; import com.dotcms.api.client.util.NamingUtils; import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.model.contenttype.AbstractSaveContentTypeRequest; import com.dotcms.model.contenttype.SaveContentTypeRequest; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.context.control.ActivateRequestContext; @@ -61,8 +62,8 @@ public ContentType add(File localFile, ContentType localContentType, final ContentTypeAPI contentTypeAPI = clientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(localContentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder() + .of(localContentType).build(); final var response = contentTypeAPI.createContentTypes(List.of(saveRequest)); return response.entity().stream() @@ -78,8 +79,8 @@ public ContentType edit(File localFile, ContentType localContentType, final ContentTypeAPI contentTypeAPI = clientFactory.getClient(ContentTypeAPI.class); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(localContentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder() + .of(localContentType).build(); final var response = contentTypeAPI.updateContentType(localContentType.variable(), saveRequest); diff --git a/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/command/contenttype/ContentTypeCommandIT.java b/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/command/contenttype/ContentTypeCommandIT.java index 3fedcf12ff6c..d30063689dad 100644 --- a/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/command/contenttype/ContentTypeCommandIT.java +++ b/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/command/contenttype/ContentTypeCommandIT.java @@ -2345,6 +2345,66 @@ void Test_Command_Content_Find_Authenticated_With_Token() { } } + /** + * Given scenario: Testing the Content Type push command and checking the base type. + * Expected Result: The base type on the server should the same as the one on the descriptor before + * and after the push operation. + * + * @throws IOException if an I/O error occurs during the execution of the test + */ + @Test + void Test_Push_Content_Type_Update_Checking_Base_Type() throws IOException { + + // Create a temporal folder for the workspace + var tempFolder = createTempFolder(); + final Workspace workspace = workspaceManager.getOrCreate(tempFolder); + + final CommandLine commandLine = createCommand(); + final StringWriter writer = new StringWriter(); + try (PrintWriter out = new PrintWriter(writer)) { + + commandLine.setOut(out); + commandLine.setErr(out); + + // ╔══════════════════════╗ + // ║ Preparing the data ║ + // ╚══════════════════════╝ + // Creating a HTML page content type file descriptor + final var newContentTypeResult = contentTypesTestHelper.createPageContentTypeDescriptor( + workspace + ); + + // ╔════════════════════════════════════════════════════════════╗ + // ║ Pushing the descriptor for the just created Content Type ║ + // ╚════════════════════════════════════════════════════════════╝ + var status = commandLine.execute(ContentTypeCommand.NAME, ContentTypePush.NAME, + workspace.contentTypes().toAbsolutePath().toString(), + "--fail-fast", "-e"); + Assertions.assertEquals(CommandLine.ExitCode.OK, status); + + // ╔════════════════════════════════════════════╗ + // ║ Validating the information on the server ║ + // ╚════════════════════════════════════════════╝ + var byVarName = contentTypesTestHelper.findContentType(newContentTypeResult.variable()); + Assertions.assertTrue(byVarName.isPresent()); + Assertions.assertEquals(BaseContentType.HTMLPAGE, byVarName.get().baseType()); + + // --- + // Now validating the auto update updated the content type descriptor + var updatedContentTypeDescriptor = this.mapperService.map( + newContentTypeResult.path().toFile(), + ContentType.class + ); + Assertions.assertNotNull(updatedContentTypeDescriptor.fields()); + Assertions.assertEquals( + BaseContentType.HTMLPAGE, updatedContentTypeDescriptor.baseType() + ); + + } finally { + deleteTempDirectory(tempFolder); + } + } + /** * Function to verify if a list of strings is sorted in ascending order (case-insensitive) * diff --git a/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/common/ContentTypesTestHelperService.java b/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/common/ContentTypesTestHelperService.java index d4b9de8c86f3..3e2c135ce114 100644 --- a/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/common/ContentTypesTestHelperService.java +++ b/tools/dotcms-cli/cli/src/test/java/com/dotcms/cli/common/ContentTypesTestHelperService.java @@ -10,10 +10,12 @@ import com.dotcms.contenttype.model.field.ImmutableTextField; import com.dotcms.contenttype.model.type.BaseContentType; import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.contenttype.model.type.ImmutablePageContentType; import com.dotcms.contenttype.model.type.ImmutableSimpleContentType; import com.dotcms.contenttype.model.workflow.ImmutableWorkflow; import com.dotcms.model.ResponseEntityView; import com.dotcms.model.config.Workspace; +import com.dotcms.model.contenttype.AbstractSaveContentTypeRequest; import com.dotcms.model.contenttype.SaveContentTypeRequest; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.enterprise.context.ApplicationScoped; @@ -67,8 +69,8 @@ public String createContentTypeOnServer(final String detailPage, final String ur null, null, detailPage, urlMapPattern ); - final SaveContentTypeRequest saveRequest = SaveContentTypeRequest.builder(). - from(contentType).build(); + final SaveContentTypeRequest saveRequest = AbstractSaveContentTypeRequest.builder() + .of(contentType).build(); contentTypeAPI.createContentTypes(List.of(saveRequest)); // Make sure the content type is created, and we are giving the server some time to process @@ -79,6 +81,18 @@ public String createContentTypeOnServer(final String detailPage, final String ur return contentType.variable(); } + /** + * Creates a HTML page content type descriptor in the given workspace. + * + * @param workspace The workspace in which the content type descriptor should be created. + * @return The result of the content type descriptor creation. + * @throws IOException If an error occurs while writing the content type descriptor to disk. + */ + public ContentTypeDescriptorCreationResult createPageContentTypeDescriptor(Workspace workspace) + throws IOException { + return createPageContentTypeDescriptor(workspace, null, null); + } + /** * Creates a content type descriptor in the given workspace. * @@ -158,6 +172,33 @@ public ContentTypeDescriptorCreationResult createContentTypeDescriptor( return new ContentTypeDescriptorCreationResult(contentType.variable(), path); } + /** + * Creates a HTML page content type descriptor in the given workspace. + * + * @param workspace The workspace in which the content type descriptor should be created. + * @param identifier The identifier of the content type. + * @param variable The variable of the content type. + * @return The result of the content type descriptor creation. + * @throws IOException If an error occurs while writing the content type descriptor to disk. + */ + public ContentTypeDescriptorCreationResult createPageContentTypeDescriptor( + Workspace workspace, final String identifier, final String variable) + throws IOException { + + final ImmutablePageContentType contentType = buildPageContentType( + identifier, variable + ); + + final ObjectMapper objectMapper = new ClientObjectMapper().getContext(null); + final String asString = objectMapper.writeValueAsString(contentType); + + final Path path = Path.of(workspace.contentTypes().toString(), + String.format("%s.json", contentType.variable())); + Files.writeString(path, asString); + + return new ContentTypeDescriptorCreationResult(contentType.variable(), path); + } + /** * Builds a content type object. * @@ -232,6 +273,76 @@ private ImmutableSimpleContentType buildContentType(final String identifier, return builder.build(); } + /** + * Builds a HTML page content type object. + * + * @param identifier The identifier of the content type. + * @param variable The variable of the content type. + * @return The content type object. + */ + private ImmutablePageContentType buildPageContentType( + final String identifier, final String variable) { + + final long millis = System.currentTimeMillis(); + final String contentTypeVariable = Objects.requireNonNullElseGet(variable, + () -> "var_" + millis); + + var builder = ImmutablePageContentType.builder() + .baseType(BaseContentType.HTMLPAGE) + .description("ct for testing.") + .name("name-" + contentTypeVariable) + .variable(contentTypeVariable) + .modDate(new Date()) + .fixed(true) + .iDate(new Date()) + .host("SYSTEM_HOST") + .folder("SYSTEM_FOLDER") + .addFields( + ImmutableBinaryField.builder() + .name("__bin_var__" + millis) + .fixed(false) + .listed(true) + .searchable(true) + .unique(false) + .indexed(true) + .readOnly(false) + .forceIncludeInApi(false) + .modDate(new Date()) + .required(false) + .variable("lol") + .sortOrder(1) + .dataType(DataTypes.SYSTEM).build(), + ImmutableTextField.builder() + .indexed(true) + .dataType(DataTypes.TEXT) + .fieldType("text") + .readOnly(false) + .required(true) + .searchable(true) + .listed(true) + .sortOrder(2) + .searchable(true) + .name("Name") + .variable("name") + .fixed(false) + .build() + ) + .workflows( + List.of( + ImmutableWorkflow.builder() + .id(SYSTEM_WORKFLOW_ID) + .variableName(SYSTEM_WORKFLOW_VARIABLE_NAME) + .build() + ) + ); + + if (identifier != null) { + builder.id(identifier); + } + + return builder.build(); + } + /** * Searches for a content type by its variable. * From 74085712b962fba3932beb04a52140ce5d7938ab Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 31 Oct 2024 13:47:38 -0600 Subject: [PATCH 07/11] #30472 adding postman to check shortyId (#30514) Adding postman to check if shortyId is there --- .../ContentResourceV1.postman_collection.json | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/dotcms-postman/src/main/resources/postman/ContentResourceV1.postman_collection.json b/dotcms-postman/src/main/resources/postman/ContentResourceV1.postman_collection.json index 9737cf41313f..bb85b4ab07f3 100644 --- a/dotcms-postman/src/main/resources/postman/ContentResourceV1.postman_collection.json +++ b/dotcms-postman/src/main/resources/postman/ContentResourceV1.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "05e460a0-406c-42b4-a8e7-0d61a8c6f794", + "_postman_id": "015f66fd-6d09-4641-873d-03e8b08011f4", "name": "ContentResourceV1", "description": "This folder contains a comprehensive set of API requests related to the `ContentResourceV1` API endpoints. These requests cover various operations such as creating, retrieving and updating content. The folder is organized to help developers and testers efficiently validate and interact with the content resource endpoints in the system.\n\n#### Objectives:\n\n1. **Create Content**:\n \n - Test the creation of new content items with valid and invalid data.\n \n - Ensure that the response includes all necessary details for the created content.\n \n2. **Retrieve Content**:\n \n - Validate the retrieval of content items by ID.\n \n - Ensure the response contains accurate and complete content details.\n \n3. **Update Content**:\n \n - Test updating existing content items with valid and invalid data.\n \n - Verify that the response reflects the updated content accurately.\n \n - Ensure that only authorized users can update content.\n \n4. **Error Handling**:\n \n - Verify that the API returns appropriate error messages for invalid requests.\n \n - Ensure the correct HTTP status codes are used for different error scenarios.\n \n5. **Security**:\n \n - Validate that only authorized users can perform operations on the content.\n \n - Ensure that all security protocols are enforced during API interactions.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", @@ -474,11 +474,16 @@ "listen": "test", "script": { "exec": [ + "var jsonData = pm.response.json();", + "", "pm.test(\"Valid response\", function () {", " pm.expect(pm.response.text()).to.include(\"SucessRequest\");", + "", + " pm.expect(jsonData.entity).to.have.property('shortyId');", + " pm.expect(jsonData.entity).to.have.property('identifier');", "});", "", - "var jsonData = pm.response.json();", + "", "pm.collectionVariables.set(\"contentletIdentifier\", jsonData.entity.identifier);", "pm.collectionVariables.set(\"contentletInode\", jsonData.entity.inode);", "", @@ -490,6 +495,16 @@ } ], "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, "method": "PUT", "header": [ { @@ -499,7 +514,7 @@ ], "body": { "mode": "raw", - "raw": "{ \"contentlet\" : {\n \"stInode\" : \"f4d7c1b8-2c88-4071-abf1-a5328977b07d\",\n \"languageId\" : 1,\n \"key\": \"SucessRequest{{$timestamp}}\",\n \"value\": \"SucessRequest{{$timestamp}}\"\n}\n}" + "raw": "{\n \"contentlet\": {\n \"stInode\": \"f4d7c1b8-2c88-4071-abf1-a5328977b07d\",\n \"languageId\": 1,\n \"key\": \"SucessRequest{{$timestamp}}\",\n \"value\": \"SucessRequest{{$timestamp}}\"\n }\n}" }, "url": { "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", @@ -2871,6 +2886,14 @@ { "key": "contentIdentifier", "value": "" + }, + { + "key": "contentletIdentifier", + "value": "" + }, + { + "key": "contentletInode", + "value": "" } ] } \ No newline at end of file From 3f5e10d9ad46dec9bb323c7794926789c8ae7dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Enrique=20Colina=20Rodr=C3=ADguez?= Date: Thu, 31 Oct 2024 21:04:15 +0100 Subject: [PATCH 08/11] feat: Create deployartifactjavadoc composite action base (#28550) (#30535) ### Proposed Changes * This Pull Request introduces a new composite action named deploy-javadoc, based on the Generate/Push Javadoc step from maven-release-process.yml. The main objective of this action is to modularize the behavior for generating and deploying Javadocs, providing a more reusable and consistent solution within the CI/CD workflow. ### Key changes: - Integration with the maven-job action to reuse artifacts from previous stages. - Use of Maven cache to optimize performance. - Availability of Java classes generated during the compilation process, essential for creating immutable objects. ### Additional Info This PR resolves #28550 (Create deploy-javadoc composite action base). --- .../deployment/deploy-javadoc/README.md | 72 +++++++++++++++++ .../deployment/deploy-javadoc/action.yml | 78 +++++++++++++++++++ .../actions/core-cicd/maven-job/action.yml | 2 + .../legacy-release_maven-release-process.yml | 2 +- 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 .github/actions/core-cicd/deployment/deploy-javadoc/README.md create mode 100644 .github/actions/core-cicd/deployment/deploy-javadoc/action.yml diff --git a/.github/actions/core-cicd/deployment/deploy-javadoc/README.md b/.github/actions/core-cicd/deployment/deploy-javadoc/README.md new file mode 100644 index 000000000000..8cb3cf6ff745 --- /dev/null +++ b/.github/actions/core-cicd/deployment/deploy-javadoc/README.md @@ -0,0 +1,72 @@ +# Deploy Artifact Javadoc Composite Action + +This GitHub composite action deploys Javadoc artifacts to the GitHub Packages registry and an AWS S3 bucket. It uses Maven to generate the Javadocs and AWS CLI to upload the generated documentation to a specified S3 URI. + +## Inputs + +- **ref**: + *Description*: Branch to build from. + *Required*: No + *Default*: `main` + +- **github-token**: + *Description*: GitHub Token for authentication. + *Required*: Yes + +- **release-version**: + *Description*: The version of the release. + *Required*: Yes + +- **artifact-run-id**: + *Description*: The run ID of the core artifacts to restore classes from. + *Required*: No + +- **aws-access-key-id**: + *Description*: AWS Access Key ID for authentication. + *Required*: Yes + +- **aws-secret-access-key**: + *Description*: AWS Secret Access Key for authentication. + *Required*: Yes + +- **aws-region**: + *Description*: AWS region for deployment. + *Required*: Yes + *Default*: `us-east-1` + +## Steps + +1. **Checkout**: Uses the `actions/checkout@v4` action to check out the specified branch. +2. **Maven Clean Build**: Runs a Maven clean install to build the project (skipping tests), only if `artifact-run-id` is not provided. +3. **Deploy Javadoc**: Runs Maven to generate Javadocs and restores classes from the specified artifact run ID if provided. +4. **Configure AWS Credentials**: Configures AWS credentials using the `aws-actions/configure-aws-credentials@v1` action. +5. **Generate/Push Javadoc**: Uploads the generated Javadoc to an S3 bucket using the AWS CLI. + +## Example Usage + +```yaml +name: Deploy Javadoc Workflow +on: + push: + branches: + - main + +jobs: + deploy-javadoc: + runs-on: ubuntu-latest + steps: + - name: Deploy Artifact Javadoc + uses: ./.github/actions/deploy-artifact-javadoc + with: + ref: 'main' + github-token: ${{ secrets.GITHUB_TOKEN }} + release-version: '1.0.0' + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: 'us-east-1' +``` + +# Notes + +- Ensure that the github-token, aws-access-key-id, and aws-secret-access-key inputs are provided securely using GitHub secrets. +- The artifact-run-id is optional and can be used to restore classes from previous artifact runs if necessary. diff --git a/.github/actions/core-cicd/deployment/deploy-javadoc/action.yml b/.github/actions/core-cicd/deployment/deploy-javadoc/action.yml new file mode 100644 index 000000000000..a544a034dee2 --- /dev/null +++ b/.github/actions/core-cicd/deployment/deploy-javadoc/action.yml @@ -0,0 +1,78 @@ +name: Deploy Artifact Javadoc +description: Deploys the Javadoc artifact to the GitHub Packages registry +inputs: + ref: + description: 'Branch to build from' + required: false + default: 'main' + github-token: + description: 'GitHub Token' + required: true + release-version: + description: 'The version of the release' + required: true + artifact-run-id: + description: 'The run id of the core artifacts' + aws-access-key-id: + description: 'AWS Access Key ID' + required: true + aws-secret-access-key: + description: 'AWS Secret Access Key' + required: true + aws-region: + description: 'AWS region' + default: 'us-east-1' + required: true + +runs: + using: "composite" + steps: + - name: 'Checkout' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - uses: ./.github/actions/core-cicd/maven-job + id: maven-clean + with: + stage-name: "Clean Build" + maven-args: "clean install -DskipTests" + generate-docker: false + cleanup-runner: true + github-token: ${{ inputs.github-token }} + if: inputs.artifact-run-id == '' + + - uses: ./.github/actions/core-cicd/maven-job + id: maven-javadoc + with: + stage-name: "Deploy Javadoc" + maven-args: "javadoc:javadoc -pl :dotcms-core" + generate-docker: false + cleanup-runner: true + restore-classes: true + artifacts-from: ${{ inputs.artifact-run-id }} + github-token: ${{ inputs.github-token }} + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ inputs.aws-access-key-id }} + aws-secret-access-key: ${{ inputs.aws-secret-access-key }} + aws-region: ${{ inputs.aws-region }} + + - name: Generate/Push Javadoc + if: success() + run: | + echo "::group::Generate/Push Javadoc" + site_dir=./dotCMS/target/site + javadoc_dir=${site_dir}/javadocs + s3_uri=s3://static.dotcms.com/docs/${{ inputs.release-version }}/javadocs + mv ${site_dir}/apidocs ${javadoc_dir} + # ls -R $javadoc_dir + echo "Running: aws s3 cp ${javadoc_dir} ${s3_uri} --recursive" + aws s3 cp ${javadoc_dir} ${s3_uri} --recursive + echo "::endgroup::" + env: + AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} + shell: bash \ No newline at end of file diff --git a/.github/actions/core-cicd/maven-job/action.yml b/.github/actions/core-cicd/maven-job/action.yml index 6dc242f04fd7..eade3711b4d9 100644 --- a/.github/actions/core-cicd/maven-job/action.yml +++ b/.github/actions/core-cicd/maven-job/action.yml @@ -259,6 +259,8 @@ runs: name: "build-classes" path: | **/target/classes/**/*.class + **/target/generated-sources/**/*.java + **/target/test-classes/**/*.class LICENSE - id: delete-built-artifacts-from-cache diff --git a/.github/workflows/legacy-release_maven-release-process.yml b/.github/workflows/legacy-release_maven-release-process.yml index 5f5050d36fb8..9959dbcdfc33 100644 --- a/.github/workflows/legacy-release_maven-release-process.yml +++ b/.github/workflows/legacy-release_maven-release-process.yml @@ -433,4 +433,4 @@ jobs: SLACK_FOOTER: "" SLACK_ICON: https://avatars.slack-edge.com/temp/2021-12-08/2830145934625_e4e464d502865ff576e4.png SLACK_MESSAGE: " This automated script is excited to announce the release of a new version of dotCMS `${{ needs.prepare-release.outputs.release_version }}` :rocket:\n:docker: Produced images: [${{ needs.build-push-image.outputs.formatted_tags }}]" - if: success() && github.event.inputs.notify_slack == 'true' + if: success() && github.event.inputs.notify_slack == 'true' \ No newline at end of file From 1bbd500dad6cfec4168bd33755b103ada5875765 Mon Sep 17 00:00:00 2001 From: freddyDOTCMS <147462678+freddyDOTCMS@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:29:38 -0600 Subject: [PATCH 09/11] Issue 30468 remove calls to elastic read only command and disable es read only monitor job (#30471) ### Proposed Changes * Remove all the Used of the ES Read Only Monitor, we still are not removing all the logic --------- Co-authored-by: Will Ezell --- .../business/ContentletIndexAPIImpl.java | 4 -- .../business/ESContentletAPIImpl.java | 7 --- .../common/reindex/ReindexThread.java | 25 ++++++----- .../dotmarketing/init/DotInitScheduler.java | 2 +- .../business/ESContentletAPIImplTest.java | 45 ------------------- 5 files changed, 15 insertions(+), 68 deletions(-) diff --git a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImpl.java b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImpl.java index c541f932361b..ded190219e10 100644 --- a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImpl.java +++ b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImpl.java @@ -553,10 +553,6 @@ public void addContentToIndex(final Contentlet parentContenlet, .build() : List.of(parentContenlet); - if (ElasticReadOnlyCommand.getInstance().isIndexOrClusterReadOnly()) { - ElasticReadOnlyCommand.getInstance().sendReadOnlyMessage(); - } - if (parentContenlet.getIndexPolicy() == IndexPolicy.DEFER) { queueApi.addContentletsReindex(contentToIndex); } else if (!DbConnectionFactory.inTransaction()) { diff --git a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java index a8bc97ab39b2..8f27e6eb9454 100644 --- a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java +++ b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java @@ -5311,13 +5311,6 @@ private Contentlet internalCheckin(Contentlet contentlet, if (!isCheckInSafe(contentRelationships)) { - if (contentlet.getBoolProperty(Contentlet.IS_TEST_MODE)) { - this.elasticReadOnlyCommand.executeCheck(); - } else { - DotConcurrentFactory.getInstance().getSingleSubmitter() - .submit(() -> this.elasticReadOnlyCommand.executeCheck()); - } - final String contentletIdentifier = null != contentlet && null != contentlet.getIdentifier() ? contentlet.getIdentifier() : StringPool.NULL; diff --git a/dotCMS/src/main/java/com/dotmarketing/common/reindex/ReindexThread.java b/dotCMS/src/main/java/com/dotmarketing/common/reindex/ReindexThread.java index c5992c26fe98..c2c7f958261c 100644 --- a/dotCMS/src/main/java/com/dotmarketing/common/reindex/ReindexThread.java +++ b/dotCMS/src/main/java/com/dotmarketing/common/reindex/ReindexThread.java @@ -213,8 +213,7 @@ private void runReindexLoop() { bulkProcessor = finalizeReIndex(bulkProcessor); } - if (!workingRecords.isEmpty() && !ElasticReadOnlyCommand.getInstance() - .isIndexOrClusterReadOnly()) { + if (!workingRecords.isEmpty()) { Logger.debug(this, "Found " + workingRecords + " index items to process"); @@ -235,15 +234,19 @@ private void runReindexLoop() { } finally { DbConnectionFactory.closeSilently(); } - while (state.get() == ThreadState.PAUSED) { - ThreadUtils.sleep(SLEEP); - //Logs every 60 minutes - Logger.infoEvery(ReindexThread.class, "--- ReindexThread Paused", - Config.getIntProperty("REINDEX_THREAD_PAUSE_IN_MINUTES", 60) * 60000); - Long restartTime = (Long) cache.get().get(REINDEX_THREAD_PAUSED); - if (restartTime == null || restartTime < System.currentTimeMillis()) { - state.set(ThreadState.RUNNING); - } + sleep(); + } + } + + private void sleep() { + while (state.get() == ThreadState.PAUSED) { + ThreadUtils.sleep(SLEEP); + //Logs every 60 minutes + Logger.infoEvery(ReindexThread.class, "--- ReindexThread Paused", + Config.getIntProperty("REINDEX_THREAD_PAUSE_IN_MINUTES", 60) * 60000); + Long restartTime = (Long) cache.get().get(REINDEX_THREAD_PAUSED); + if (restartTime == null || restartTime < System.currentTimeMillis()) { + state.set(ThreadState.RUNNING); } } } diff --git a/dotCMS/src/main/java/com/dotmarketing/init/DotInitScheduler.java b/dotCMS/src/main/java/com/dotmarketing/init/DotInitScheduler.java index df6b1d9e8426..5b6ca319aecd 100644 --- a/dotCMS/src/main/java/com/dotmarketing/init/DotInitScheduler.java +++ b/dotCMS/src/main/java/com/dotmarketing/init/DotInitScheduler.java @@ -406,7 +406,7 @@ private static void addElasticReadyOnlyMonitor (final Scheduler scheduler) { final String triggerName = "trigger29"; final String triggerGroup = "group98"; - if (Config.getBooleanProperty( "ENABLE_ELASTIC_READ_ONLY_MONITOR", true)) { + if (Config.getBooleanProperty( "ENABLE_ELASTIC_READ_ONLY_MONITOR", false)) { final JobBuilder elasticReadOnlyMonitorJob = new JobBuilder().setJobClass(EsReadOnlyMonitorJob.class) .setJobName(jobName) diff --git a/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java b/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java index 837d61a86980..f694254e4916 100644 --- a/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java +++ b/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java @@ -277,51 +277,6 @@ public void testGetRelatedContentFromMultilingualContent() } } - @Test() - public void testCheckInWithLegacyRelationshipsAndReadOnlyClusterShouldThrowAnException() - throws DotDataException, DotSecurityException { - final long time = System.currentTimeMillis(); - ContentType contentType = null; - final ElasticReadOnlyCommand esReadOnlyMonitor = mock(ElasticReadOnlyCommand.class); - final ESContentletAPIImpl contentletAPIImpl = new ESContentletAPIImpl(esReadOnlyMonitor); - - try { - contentType = createContentType("test" + time); - - final Structure structure = new StructureTransformer(contentType).asStructure(); - - final Contentlet contentlet = new ContentletDataGen(contentType.id()).next(); - final ContentletRelationships contentletRelationship = new ContentletRelationships( - contentlet); - - final Relationship relationship = new Relationship(structure, structure, - "parent" + contentType.variable(), "child" + contentType.variable(), - RELATIONSHIP_CARDINALITY.ONE_TO_MANY.ordinal(), false, false); - - final ContentletRelationshipRecords relationshipsRecord = contentletRelationship.new ContentletRelationshipRecords( - relationship, - false); - - contentletRelationship - .setRelationshipsRecords(CollectionsUtils.list(relationshipsRecord)); - - setClusterAsReadOnly(true); - - contentlet.setProperty(Contentlet.IS_TEST_MODE, true); - contentletAPIImpl.checkin(contentlet, contentletRelationship, null, null, user, false); - - throw new AssertionError("DotContentletStateException Expected"); - } catch(DotContentletStateException e) { - verify(esReadOnlyMonitor).executeCheck(); - }finally{ - if (contentType != null && contentType.id() != null){ - contentTypeAPI.delete(contentType); - } - - setClusterAsReadOnly(false); - } - } - /** * Test for isCheckInSafe method with legacy relationships. It should return false when the cluster * is in read only mode From 3b0884e7890fe0ccd3e09698d20de4f450c493f8 Mon Sep 17 00:00:00 2001 From: Rafael Velazco Date: Fri, 1 Nov 2024 10:48:07 -0400 Subject: [PATCH 10/11] SDK: Unable to Edit Unpublished Page in Angular Example (#30542) This pull request includes several updates to the `DotCMSPagesComponent` in the Angular example application. The changes primarily focus on integrating editor-related functionality and improving code formatting. ### Editor Integration: * Added `DOTCMS_CLIENT_TOKEN` import and injected it into the `DotCMSPagesComponent` to enable editor-related functionalities. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L20-R26) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395R66-R85) * Implemented a new method `#listenToEditorChanges` to handle editor changes and update the component state accordingly. ### Code Formatting: * Reformatted the import statements for better readability and maintainability. * Adjusted the method signature formatting for `#setPageContent` to be consistent with the rest of the codebase. ### Video https://github.com/user-attachments/assets/7ee487ce-412f-4504-8ff1-f92dac86beee --------- Co-authored-by: Jalinson Diaz --- .../angular/src/app/pages/pages.component.ts | 34 +++++++++++++++---- .../src/app/pages/services/page.service.ts | 4 +-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/examples/angular/src/app/pages/pages.component.ts b/examples/angular/src/app/pages/pages.component.ts index 45fbf51a3dfb..f57e58be2c52 100644 --- a/examples/angular/src/app/pages/pages.component.ts +++ b/examples/angular/src/app/pages/pages.component.ts @@ -17,8 +17,13 @@ import { HeaderComponent } from './components/header/header.component'; import { NavigationComponent } from './components/navigation/navigation.component'; import { FooterComponent } from './components/footer/footer.component'; import { PageService } from './services/page.service'; -import { CUSTOMER_ACTIONS, postMessageToEditor } from '@dotcms/client'; +import { + CLIENT_ACTIONS, + isInsideEditor, + postMessageToEditor, +} from '@dotcms/client'; import { DYNAMIC_COMPONENTS } from './components'; +import { DOTCMS_CLIENT_TOKEN } from '../app.config'; export type PageError = { message: string; @@ -51,6 +56,8 @@ export class DotCMSPagesComponent implements OnInit { readonly #destroyRef = inject(DestroyRef); readonly #router = inject(Router); readonly #pageService = inject(PageService); + readonly #client = inject(DOTCMS_CLIENT_TOKEN); + protected readonly $context = signal({ page: null, nav: null, @@ -63,6 +70,10 @@ export class DotCMSPagesComponent implements OnInit { protected readonly editorCofig: any = { params: { depth: 2 } }; ngOnInit() { + if (isInsideEditor()) { + this.#listenToEditorChanges(); + } + this.#router.events .pipe( filter( @@ -90,10 +101,7 @@ export class DotCMSPagesComponent implements OnInit { }); } - #setPageContent( - page: DotCMSPageAsset, - nav: DotcmsNavigationItem | null - ) { + #setPageContent(page: DotCMSPageAsset, nav: DotcmsNavigationItem | null) { this.$context.set({ status: 'success', page, @@ -122,6 +130,20 @@ export class DotCMSPagesComponent implements OnInit { * This is a temporary workaround to avoid the editor to be stuck in the loading state. * This will be removed once the editor is able to detect when the client is ready without use DotcmsLayoutComponent. */ - postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY, payload: {} }); + postMessageToEditor({ action: CLIENT_ACTIONS.CLIENT_READY, payload: {} }); + } + + #listenToEditorChanges() { + this.#client.editor.on('changes', (page) => { + if (!page) { + return; + } + this.$context.update((state) => ({ + ...state, + page: page as DotCMSPageAsset, + status: 'success', + error: null, + })); + }); } } diff --git a/examples/angular/src/app/pages/services/page.service.ts b/examples/angular/src/app/pages/services/page.service.ts index 6efbd088e1aa..f55dc8dc9d44 100644 --- a/examples/angular/src/app/pages/services/page.service.ts +++ b/examples/angular/src/app/pages/services/page.service.ts @@ -75,13 +75,13 @@ export class PageService { route: ActivatedRoute, config: any ): Observable { - const queryParams = route.snapshot.queryParamMap; + const params = route.snapshot.queryParams; const url = route.snapshot.url.map((segment) => segment.path).join('/'); const path = url || '/'; const pageParams = getPageRequestParams({ path, - params: queryParams, + params }); return from(this.client.page.get({ ...pageParams, ...config.params })).pipe( From 011883f5cdb2620fd28b288e59a37bb4bd69898e Mon Sep 17 00:00:00 2001 From: Jalinson Diaz Date: Fri, 1 Nov 2024 13:11:36 -0300 Subject: [PATCH 11/11] fix(examples): Update naming (#30540) This pull request includes several changes to improve code consistency, readability, and correctness across different files. The most important changes involve import statement adjustments, formatting improvements, and updating action names. ### Import Statement Adjustments: * [`examples/angular/src/app/pages/pages.component.ts`](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L7-R7): Combined multiple imports from `@dotcms/angular` into a single line and updated `CUSTOMER_ACTIONS` to `CLIENT_ACTIONS` from `@dotcms/client`. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L7-R7) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L20-R16) * [`examples/astro/src/react/hooks/usePageAsset.ts`](diffhunk://#diff-15921ced32cc4a42067d2c1f36400763b0d8c40193419af67ed8c8d77751c9eaL3-R3): Updated `CUSTOMER_ACTIONS` to `CLIENT_ACTIONS` from `@dotcms/client`. * [`examples/nextjs/src/hooks/usePageAsset.js`](diffhunk://#diff-8fa464b336a283f1eec51ffef29c76c8ae0f2d19f32d8829851694636472b4aaL1-R4): Updated `CUSTOMER_ACTIONS` to `CLIENT_ACTIONS` from `@dotcms/client` and adjusted import formatting. [[1]](diffhunk://#diff-8fa464b336a283f1eec51ffef29c76c8ae0f2d19f32d8829851694636472b4aaL1-R4) [[2]](diffhunk://#diff-8fa464b336a283f1eec51ffef29c76c8ae0f2d19f32d8829851694636472b4aaL18-R14) [[3]](diffhunk://#diff-8fa464b336a283f1eec51ffef29c76c8ae0f2d19f32d8829851694636472b4aaL28-R30) ### Formatting Improvements: * [`examples/angular/src/app/pages/pages.component.ts`](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L44-R43): Improved formatting for better readability by aligning code and removing unnecessary spaces. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L44-R43) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L58-R54) [[3]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L68-R69) [[4]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395R85-R120) * [`examples/angular/src/app/pages/services/page.service.ts`](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L22-R22): Improved formatting and alignment for better readability. [[1]](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L22-R22) [[2]](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L36-R43) [[3]](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L56-R59) [[4]](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L74-R76) [[5]](diffhunk://#diff-c28435c294bcf4c2159724ac9f83e80369fc594d661684535e1b1a770320b9c8L95-R88) ### Action Name Updates: * Updated `CUSTOMER_ACTIONS.CLIENT_READY` to `CLIENT_ACTIONS.CLIENT_READY` in various files to ensure consistency with the action naming convention. [[1]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395L20-R16) [[2]](diffhunk://#diff-db19dde961c6af3dbddd86db7544e4ea4ff42baae9095cee4e3017c1d4dcb395R85-R120) [[3]](diffhunk://#diff-15921ced32cc4a42067d2c1f36400763b0d8c40193419af67ed8c8d77751c9eaL27-R27) [[4]](diffhunk://#diff-8fa464b336a283f1eec51ffef29c76c8ae0f2d19f32d8829851694636472b4aaL28-R30) --------- Co-authored-by: Rafael Velazco --- examples/angular/package-lock.json | 2141 +++++++-------- examples/astro/package-lock.json | 2325 ++++++++--------- .../astro/src/react/hooks/usePageAsset.ts | 4 +- examples/nextjs/package-lock.json | 1377 ++++++---- examples/nextjs/package.json | 4 +- examples/nextjs/src/hooks/usePageAsset.js | 16 +- 6 files changed, 2809 insertions(+), 3058 deletions(-) diff --git a/examples/angular/package-lock.json b/examples/angular/package-lock.json index 15e236515a51..3d7a2278cde1 100644 --- a/examples/angular/package-lock.json +++ b/examples/angular/package-lock.json @@ -16,8 +16,8 @@ "@angular/platform-browser": "^17.1.0", "@angular/platform-browser-dynamic": "^17.1.0", "@angular/router": "^17.1.0", - "@dotcms/angular": "0.0.1-alpha.37", - "@dotcms/client": "0.0.1-alpha.37", + "@dotcms/angular": "latest", + "@dotcms/client": "latest", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.2" @@ -67,13 +67,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1703.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.8.tgz", - "integrity": "sha512-lKxwG4/QABXZvJpqeSIn/kAwnY6MM9HdHZUV+o5o3UiTi+vO8rZApG4CCaITH3Bxebm7Nam7Xbk8RuukC5rq6g==", + "version": "0.1703.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.11.tgz", + "integrity": "sha512-YNasVZk4rYdcM6M+KRH8PUBhVyJfqzUYLpO98GgRokW+taIDgifckSlmfDZzQRbw45qiwei1IKCLqcpC8nM5Tw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", + "@angular-devkit/core": "17.3.11", "rxjs": "7.8.1" }, "engines": { @@ -83,16 +83,16 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.8.tgz", - "integrity": "sha512-ixsdXggWaFRP7Jvxd0AMukImnePuGflT9Yy7NJ9/y0cL/k//S/3RnkQv5i411KzN+7D4RIbNkRGGTYeqH24zlg==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.11.tgz", + "integrity": "sha512-lHX5V2dSts328yvo/9E2u9QMGcvJhbEKKDDp9dBecwvIG9s+4lTOJgi9DPUE7W+AtmPcmbbhwC2JRQ/SLQhAoA==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1703.8", - "@angular-devkit/build-webpack": "0.1703.8", - "@angular-devkit/core": "17.3.8", + "@angular-devkit/architect": "0.1703.11", + "@angular-devkit/build-webpack": "0.1703.11", + "@angular-devkit/core": "17.3.11", "@babel/core": "7.24.0", "@babel/generator": "7.23.6", "@babel/helper-annotate-as-pure": "7.22.5", @@ -103,7 +103,7 @@ "@babel/preset-env": "7.24.0", "@babel/runtime": "7.24.0", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "17.3.8", + "@ngtools/webpack": "17.3.11", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.18", @@ -115,7 +115,7 @@ "css-loader": "6.10.0", "esbuild-wasm": "0.20.1", "fast-glob": "3.3.2", - "http-proxy-middleware": "2.0.6", + "http-proxy-middleware": "2.0.7", "https-proxy-agent": "7.0.4", "inquirer": "9.2.15", "jsonc-parser": "3.2.1", @@ -145,9 +145,9 @@ "tree-kill": "1.2.2", "tslib": "2.6.2", "undici": "6.11.1", - "vite": "5.1.7", + "vite": "5.1.8", "watchpack": "2.4.0", - "webpack": "5.90.3", + "webpack": "5.94.0", "webpack-dev-middleware": "6.1.2", "webpack-dev-server": "4.15.1", "webpack-merge": "5.10.0", @@ -287,13 +287,13 @@ "license": "0BSD" }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1703.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.8.tgz", - "integrity": "sha512-9u6fl8VVOxcLOEMzrUeaybSvi9hSLSRucHnybneYrabsgreDo32tuy/4G8p6YAHQjpWEj9jvF9Um13ertdni5Q==", + "version": "0.1703.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.11.tgz", + "integrity": "sha512-qbCiiHuoVkD7CtLyWoRi/Vzz6nrEztpF5XIyWUcQu67An1VlxbMTE4yoSQiURjCQMnB/JvS1GPVed7wOq3SJ/w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1703.8", + "@angular-devkit/architect": "0.1703.11", "rxjs": "7.8.1" }, "engines": { @@ -307,9 +307,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", - "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz", + "integrity": "sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -335,13 +335,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", - "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.11.tgz", + "integrity": "sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", + "@angular-devkit/core": "17.3.11", "jsonc-parser": "3.2.1", "magic-string": "0.30.8", "ora": "5.4.1", @@ -369,16 +369,16 @@ } }, "node_modules/@angular/cli": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.8.tgz", - "integrity": "sha512-X5ZOQ6ZTKVHjhIsfl32ZRqbs+FUoeHLbT7x4fh2Os/8ObDDwrUcCJPqxe2b2RB5E2d0vepYigknHeLE7gwzlNQ==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.11.tgz", + "integrity": "sha512-8R9LwAGL8hGAWJ4mNG9ZPUrBUzIdmst0Ldua6RJJ+PrqgjX+8IbO+lNnfrOY/XY+Z3LXbCEJflL26f9czCvTPQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1703.8", - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", - "@schematics/angular": "17.3.8", + "@angular-devkit/architect": "0.1703.11", + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "@schematics/angular": "17.3.11", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -609,13 +609,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -623,9 +624,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "dev": true, "license": "MIT", "engines": { @@ -710,29 +711,29 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -751,18 +752,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "engines": { @@ -773,13 +774,13 @@ } }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -796,14 +797,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", - "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "engines": { @@ -814,13 +815,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -867,44 +868,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -914,22 +914,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, "license": "MIT", "engines": { @@ -937,15 +937,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", - "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-wrap-function": "^7.25.0", - "@babel/traverse": "^7.25.0" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -955,28 +955,28 @@ } }, "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -986,28 +986,28 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1027,9 +1027,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", "engines": { @@ -1037,9 +1037,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", "engines": { @@ -1047,9 +1047,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -1057,58 +1057,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", - "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", - "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.4" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1118,13 +1102,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", - "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1134,15 +1118,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1152,14 +1136,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", - "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1250,13 +1234,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1266,13 +1250,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1435,13 +1419,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1488,13 +1472,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1504,13 +1488,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", - "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1520,14 +1504,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", - "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1537,15 +1521,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1555,17 +1538,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", - "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "engines": { @@ -1576,27 +1559,27 @@ } }, "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1606,13 +1589,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1622,14 +1605,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1639,13 +1622,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1655,14 +1638,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1672,14 +1654,14 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1689,14 +1671,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1706,14 +1687,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1723,15 +1704,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", - "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.1" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1741,14 +1722,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1758,13 +1738,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", - "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1774,14 +1754,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1791,13 +1770,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1807,14 +1786,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1824,15 +1803,15 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1842,16 +1821,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", - "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1861,14 +1840,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1878,14 +1857,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1895,13 +1874,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1911,14 +1890,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1928,14 +1906,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1945,16 +1922,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1964,14 +1940,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1981,14 +1957,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1998,15 +1973,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2016,13 +1990,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2032,14 +2006,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", - "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2049,16 +2023,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2068,26 +2041,26 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2097,13 +2070,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.9", "regenerator-transform": "^0.15.2" }, "engines": { @@ -2114,13 +2087,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2161,13 +2134,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2177,14 +2150,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2194,13 +2167,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2210,13 +2183,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2226,13 +2199,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2242,13 +2215,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2258,14 +2231,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2275,14 +2248,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2292,14 +2265,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", - "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2428,13 +2401,6 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true, - "license": "MIT" - }, "node_modules/@babel/runtime": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", @@ -2449,32 +2415,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", - "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.4", - "@babel/parser": "^7.25.4", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.4", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2483,31 +2449,44 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.25.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.5.tgz", - "integrity": "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.4", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@babel/types": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", - "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2534,25 +2513,27 @@ } }, "node_modules/@dotcms/angular": { - "version": "0.0.1-alpha.37", - "resolved": "https://registry.npmjs.org/@dotcms/angular/-/angular-0.0.1-alpha.37.tgz", - "integrity": "sha512-TyR7jWf2BqBNmmO13KmNmBYssihfWlSexZwLo7T6veJxy1cWXbld1Fs655jd/nWFs+wa1gUqLxnWYpsnSgqKKQ==", + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/angular/-/angular-0.0.1-alpha.47.tgz", + "integrity": "sha512-fj4+1AxX7JEIA/YJBmzoYkw+ksZBFDP6XzTFDyNb/WQK979EdiaFZ8qobV5jresKm4s/kLw30blT715+WGu81A==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^17.1.0", - "@angular/core": "^17.1.0", - "@angular/router": "^17.1.0", - "@dotcms/client": "0.0.1-alpha.37", + "@angular/common": ">=17.0.0", + "@angular/core": ">=17.0.0", + "@angular/router": ">=17.0.0", + "@dotcms/client": "0.0.1-alpha.47", "@tinymce/tinymce-angular": "^8.0.0", - "rxjs": "^7.8.0" + "rxjs": ">=7.0.0" } }, "node_modules/@dotcms/client": { - "version": "0.0.1-alpha.37", - "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.37.tgz", - "integrity": "sha512-+uL6gP9sdWBC3RK5j1uESlU3+2bz8yDMoB8dF6a4kfnU5TQlCiuVFUCZRooXy8XrYhdzDxN/LiLsnLLbvoA67w==" + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.47.tgz", + "integrity": "sha512-rguDpPZJLpAkW9CWhEAaLTjQFsalTSmIzaoI923fzH+Awah0e11uQjTQDZmTHxb0X/wUeGZqUScWaf0KFo/Qxw==", + "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.1", @@ -2964,9 +2945,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -3160,9 +3141,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.8.tgz", - "integrity": "sha512-CjSVVa/9fzMpEDQP01SC4colKCbZwj7vUq0H2bivp8jVsmd21x9Fu0gDBH0Y9NdfAIm4eGZvmiZKMII3vIOaYQ==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz", + "integrity": "sha512-SfTCbplt4y6ak5cf2IfqdoVOsnoNdh/j6Vu+wb8WWABKwZ5yfr2S/Gk6ithSKcdIZhAF8DNBOoyk1EJuf8Xkfg==", "dev": true, "license": "MIT", "engines": { @@ -3353,9 +3334,9 @@ } }, "node_modules/@npmcli/package-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.0.tgz", - "integrity": "sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz", + "integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==", "dev": true, "license": "ISC", "dependencies": { @@ -3532,9 +3513,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", - "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", + "integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", "cpu": [ "arm" ], @@ -3546,9 +3527,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", - "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", + "integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", "cpu": [ "arm64" ], @@ -3560,9 +3541,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", - "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", + "integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", "cpu": [ "arm64" ], @@ -3574,9 +3555,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", - "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", + "integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", "cpu": [ "x64" ], @@ -3587,10 +3568,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", + "integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", + "integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", - "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", + "integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", "cpu": [ "arm" ], @@ -3602,9 +3611,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", - "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", + "integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", "cpu": [ "arm" ], @@ -3616,9 +3625,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", - "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", + "integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", "cpu": [ "arm64" ], @@ -3630,9 +3639,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", - "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", + "integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", "cpu": [ "arm64" ], @@ -3644,9 +3653,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", - "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", + "integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", "cpu": [ "ppc64" ], @@ -3658,9 +3667,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", - "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", + "integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", "cpu": [ "riscv64" ], @@ -3672,9 +3681,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", - "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", + "integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", "cpu": [ "s390x" ], @@ -3686,9 +3695,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", - "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", + "integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", "cpu": [ "x64" ], @@ -3700,9 +3709,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", - "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", + "integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", "cpu": [ "x64" ], @@ -3714,9 +3723,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", - "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", + "integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", "cpu": [ "arm64" ], @@ -3728,9 +3737,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", - "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", + "integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", "cpu": [ "ia32" ], @@ -3742,9 +3751,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", - "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", + "integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", "cpu": [ "x64" ], @@ -3756,14 +3765,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.8.tgz", - "integrity": "sha512-2g4OmSyE9YGq50Uj7fNI26P/TSAFJ7ZuirwTF2O7Xc4XRQ29/tYIIqhezpNlTb6rlYblcQuMcUZBrMfWJHcqJw==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.11.tgz", + "integrity": "sha512-tvJpTgYC+hCnTyLszYRUZVyNTpPd+C44gh5CPTcG3qkqStzXQwynQAf6X/DjtwXbUiPQF0XfF0+0R489GpdZPA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", "jsonc-parser": "3.2.1" }, "engines": { @@ -3995,32 +4004,10 @@ "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, @@ -4038,9 +4025,22 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "dev": true, "license": "MIT", "dependencies": { @@ -4089,13 +4089,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/node-forge": { @@ -4109,9 +4109,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", "dev": true, "license": "MIT" }, @@ -4401,10 +4401,20 @@ "node": ">= 0.6" } }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -4414,10 +4424,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4578,16 +4588,19 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/any-promise": { @@ -4888,9 +4901,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "license": "MIT", "dependencies": { @@ -4902,7 +4915,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -4972,9 +4985,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -4992,10 +5005,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -5175,9 +5188,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001653", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", - "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "dev": true, "funding": [ { @@ -5196,18 +5209,20 @@ "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chardet": { @@ -5323,42 +5338,6 @@ "node": ">=12" } }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cliui/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -5403,19 +5382,22 @@ } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, @@ -5457,34 +5439,24 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", + "negotiator": "~0.6.4", "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5502,13 +5474,6 @@ "dev": true, "license": "MIT" }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5590,9 +5555,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { @@ -5658,13 +5623,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -5755,82 +5720,6 @@ "postcss-media-query-parser": "^0.2.3" } }, - "node_modules/critters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/critters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/critters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/critters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/critters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/critters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5959,13 +5848,13 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -6192,9 +6081,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "dev": true, "license": "ISC" }, @@ -6251,9 +6140,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "dev": true, "license": "MIT", "dependencies": { @@ -6262,7 +6151,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -6447,9 +6336,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -6603,38 +6492,38 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -6646,9 +6535,9 @@ } }, "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "license": "MIT", "engines": { @@ -6665,15 +6554,25 @@ "ms": "2.0.0" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -6904,9 +6803,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -7218,13 +7117,13 @@ "license": "MIT" }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-property-descriptors": { @@ -7467,9 +7366,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "dev": true, "license": "MIT", "dependencies": { @@ -8052,29 +7951,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -8152,16 +8028,6 @@ "node": ">= 10.13.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -8398,22 +8264,6 @@ "source-map-support": "^0.5.5" } }, - "node_modules/karma/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/karma/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -8426,26 +8276,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/karma/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/karma/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8534,9 +8364,9 @@ } }, "node_modules/launch-editor": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.1.tgz", - "integrity": "sha512-elBx2l/tp9z99X5H/qev8uyDywVh0VXAwEbjk8kJhnc5grOFkGh7aW6q55me9xnYbss261XtnUrysZ+XvGbhQA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", "dev": true, "license": "MIT", "dependencies": { @@ -8712,121 +8542,45 @@ "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { "node": ">=8" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log4js": { @@ -8943,11 +8697,14 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -9329,9 +9086,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -9423,9 +9180,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, "license": "MIT", "engines": { @@ -9920,82 +9677,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -10086,9 +9767,9 @@ } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, @@ -10175,13 +9856,13 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -10287,9 +9968,9 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true, "license": "MIT" }, @@ -10304,9 +9985,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -10445,9 +10126,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -10466,8 +10147,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -10797,13 +10478,13 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -11013,9 +10694,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "license": "MIT", "dependencies": { @@ -11050,16 +10731,16 @@ "license": "MIT" }, "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -11067,26 +10748,37 @@ "node": ">=4" } }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", + "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, "node_modules/require-directory": { @@ -11246,13 +10938,13 @@ } }, "node_modules/rollup": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", - "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", + "integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -11262,22 +10954,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.1", - "@rollup/rollup-android-arm64": "4.21.1", - "@rollup/rollup-darwin-arm64": "4.21.1", - "@rollup/rollup-darwin-x64": "4.21.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", - "@rollup/rollup-linux-arm-musleabihf": "4.21.1", - "@rollup/rollup-linux-arm64-gnu": "4.21.1", - "@rollup/rollup-linux-arm64-musl": "4.21.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", - "@rollup/rollup-linux-riscv64-gnu": "4.21.1", - "@rollup/rollup-linux-s390x-gnu": "4.21.1", - "@rollup/rollup-linux-x64-gnu": "4.21.1", - "@rollup/rollup-linux-x64-musl": "4.21.1", - "@rollup/rollup-win32-arm64-msvc": "4.21.1", - "@rollup/rollup-win32-ia32-msvc": "4.21.1", - "@rollup/rollup-win32-x64-msvc": "4.21.1", + "@rollup/rollup-android-arm-eabi": "4.24.3", + "@rollup/rollup-android-arm64": "4.24.3", + "@rollup/rollup-darwin-arm64": "4.24.3", + "@rollup/rollup-darwin-x64": "4.24.3", + "@rollup/rollup-freebsd-arm64": "4.24.3", + "@rollup/rollup-freebsd-x64": "4.24.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.3", + "@rollup/rollup-linux-arm-musleabihf": "4.24.3", + "@rollup/rollup-linux-arm64-gnu": "4.24.3", + "@rollup/rollup-linux-arm64-musl": "4.24.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", + "@rollup/rollup-linux-riscv64-gnu": "4.24.3", + "@rollup/rollup-linux-s390x-gnu": "4.24.3", + "@rollup/rollup-linux-x64-gnu": "4.24.3", + "@rollup/rollup-linux-x64-musl": "4.24.3", + "@rollup/rollup-win32-arm64-msvc": "4.24.3", + "@rollup/rollup-win32-ia32-msvc": "4.24.3", + "@rollup/rollup-win32-x64-msvc": "4.24.3", "fsevents": "~2.3.2" } }, @@ -11497,9 +11191,9 @@ "license": "ISC" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { @@ -11551,13 +11245,6 @@ "node": ">=4" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/send/node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -11655,21 +11342,31 @@ "license": "ISC" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -11810,9 +11507,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, "license": "MIT", "dependencies": { @@ -11820,7 +11517,7 @@ "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -11906,9 +11603,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -12232,16 +11929,16 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -12268,9 +11965,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "dev": true, "license": "MIT", "dependencies": { @@ -12562,9 +12259,9 @@ "license": "MIT" }, "node_modules/tinymce": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.3.0.tgz", - "integrity": "sha512-Ls4PgYlpk73XAxBSBqbVmSl8Mb3DuNfgF01GZ0lY6/MOEVRl3IL+VxC1Oe6165e8WqbqVsxO3Qj/PmoYNvQKGQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.4.1.tgz", + "integrity": "sha512-g1Ieaio5YU+jLEQZkQyxTT8EY/im+TC/CFBPlqDBCNdsF8YQOeLMot+K6vmFOAXhNc85KhP1rC9Dn2X+iBFDGg==", "license": "GPL-2.0-or-later", "peer": true }, @@ -12581,16 +12278,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -12632,9 +12319,9 @@ "license": "Apache-2.0" }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/tuf-js": { @@ -12701,9 +12388,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.38.tgz", - "integrity": "sha512-fYmIy7fKTSFAhG3fuPlubeGaMoAd6r0rSnfEsO5nEY55i26KSLt9EH7PLQiiqPUhNqYIJvSkTy1oArIcXAbPbA==", + "version": "0.7.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.39.tgz", + "integrity": "sha512-IZ6acm6RhQHNibSt7+c09hhvsKy9WUr4DVbeq9U8o71qxyYtJpQeDxQnMrVqnIFMLcQjHO0I9wgfO2vIahht4w==", "dev": true, "funding": [ { @@ -12720,6 +12407,9 @@ } ], "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } @@ -12742,9 +12432,9 @@ "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", "engines": { @@ -12766,9 +12456,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "license": "MIT", "engines": { @@ -12832,9 +12522,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -12852,8 +12542,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -12941,9 +12631,9 @@ } }, "node_modules/vite": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz", - "integrity": "sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.8.tgz", + "integrity": "sha512-mB8ToUuSmzODSpENgvpFk2fTiU/YQ1tmcVJJ4WZbq4fPdGJkFNVcmVL5k7iDug6xzWjjuGDKAuSievIsD6H7Xw==", "dev": true, "license": "MIT", "dependencies": { @@ -13471,27 +13161,26 @@ } }, "node_modules/webpack": { - "version": "5.90.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", - "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -13499,7 +13188,7 @@ "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -13738,6 +13427,20 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack/node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -13817,78 +13520,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -13936,9 +13567,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "dev": true, "license": "ISC", "bin": { diff --git a/examples/astro/package-lock.json b/examples/astro/package-lock.json index 930c603b0297..e9d7a1f46353 100644 --- a/examples/astro/package-lock.json +++ b/examples/astro/package-lock.json @@ -12,8 +12,8 @@ "@astrojs/react": "^3.6.2", "@astrojs/tailwind": "^5.1.0", "@astrojs/vercel": "^7.8.0", - "@dotcms/client": "0.0.1-alpha.33", - "@dotcms/react": "0.0.1-alpha.33", + "@dotcms/client": "latest", + "@dotcms/react": "latest", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "astro": "^4.14.3", @@ -53,14 +53,13 @@ } }, "node_modules/@astrojs/check": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.3.tgz", - "integrity": "sha512-I6Dz45bMI5YRbp4yK2LKWsHH3/kkHRGdPGruGkLap6pqxhdcNh7oCgN04Ac+haDfc9ow5BYPGPmEhkwef15GQQ==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.4.tgz", + "integrity": "sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==", "license": "MIT", "dependencies": { - "@astrojs/language-server": "^2.14.1", - "chokidar": "^3.5.3", - "fast-glob": "^3.3.1", + "@astrojs/language-server": "^2.15.0", + "chokidar": "^4.0.1", "kleur": "^4.1.5", "yargs": "^17.7.2" }, @@ -84,28 +83,27 @@ "license": "MIT" }, "node_modules/@astrojs/language-server": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.14.1.tgz", - "integrity": "sha512-mkKtCTPRD4dyKdAqIP0zmmPyO/ZABOqFESnaVca47Dg/sAagJnDSEsDUDzNbHFh1+9Dj1o5y4iwNsxJboGdaNg==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.15.4.tgz", + "integrity": "sha512-JivzASqTPR2bao9BWsSc/woPHH7OGSGc9aMxXL4U6egVTqBycB3ZHdBJPuOCVtcGLrzdWTosAqVPz1BVoxE0+A==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.10.3", - "@astrojs/yaml2ts": "^0.2.1", + "@astrojs/yaml2ts": "^0.2.2", "@jridgewell/sourcemap-codec": "^1.4.15", - "@volar/kit": "~2.4.0", - "@volar/language-core": "~2.4.0", - "@volar/language-server": "~2.4.0", - "@volar/language-service": "~2.4.0", - "@volar/typescript": "~2.4.0", + "@volar/kit": "~2.4.7", + "@volar/language-core": "~2.4.7", + "@volar/language-server": "~2.4.7", + "@volar/language-service": "~2.4.7", "fast-glob": "^3.2.12", "muggle-string": "^0.4.1", - "volar-service-css": "0.0.61", - "volar-service-emmet": "0.0.61", - "volar-service-html": "0.0.61", - "volar-service-prettier": "0.0.61", - "volar-service-typescript": "0.0.61", - "volar-service-typescript-twoslash-queries": "0.0.61", - "volar-service-yaml": "0.0.61", + "volar-service-css": "0.0.62", + "volar-service-emmet": "0.0.62", + "volar-service-html": "0.0.62", + "volar-service-prettier": "0.0.62", + "volar-service-typescript": "0.0.62", + "volar-service-typescript-twoslash-queries": "0.0.62", + "volar-service-yaml": "0.0.62", "vscode-html-languageservice": "^5.2.0", "vscode-uri": "^3.0.8" }, @@ -126,29 +124,29 @@ } }, "node_modules/@astrojs/markdown-remark": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-5.2.0.tgz", - "integrity": "sha512-vWGM24KZXz11jR3JO+oqYU3T2qpuOi4uGivJ9SQLCAI01+vEkHC60YJMRvHPc+hwd60F7euNs1PeOEixIIiNQw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-5.3.0.tgz", + "integrity": "sha512-r0Ikqr0e6ozPb5bvhup1qdWnSPUvQu6tub4ZLYaKyG50BXZ0ej6FhGz3GpChKpH7kglRFPObJd/bDyf2VM9pkg==", "license": "MIT", "dependencies": { "@astrojs/prism": "3.1.0", "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.1", + "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", - "rehype-stringify": "^10.0.0", + "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.0", + "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", - "shiki": "^1.10.3", + "shiki": "^1.22.0", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", - "vfile": "^6.0.2" + "vfile": "^6.0.3" } }, "node_modules/@astrojs/prism": { @@ -183,17 +181,17 @@ } }, "node_modules/@astrojs/tailwind": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@astrojs/tailwind/-/tailwind-5.1.0.tgz", - "integrity": "sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@astrojs/tailwind/-/tailwind-5.1.2.tgz", + "integrity": "sha512-IvOF0W/dtHElcXvhrPR35nHmhyV3cfz1EzPitMGtU7sYy9Hci3BNK1To6FWmVuuNKPxza1IgCGetSynJZL7fOg==", "license": "MIT", "dependencies": { - "autoprefixer": "^10.4.15", - "postcss": "^8.4.28", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.47", "postcss-load-config": "^4.0.2" }, "peerDependencies": { - "astro": "^3.0.0 || ^4.0.0", + "astro": "^3.0.0 || ^4.0.0 || ^5.0.0-beta.0", "tailwindcss": "^3.0.24" } }, @@ -216,15 +214,15 @@ } }, "node_modules/@astrojs/vercel": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@astrojs/vercel/-/vercel-7.8.0.tgz", - "integrity": "sha512-cpY14PPrKhAsYZp/tfRSIfKdiPctvvPfOH8z3USLJEAJ5lLfToUHEGTJzNfGqCBtd61QftypIxIlTHGuFY30UQ==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/@astrojs/vercel/-/vercel-7.8.2.tgz", + "integrity": "sha512-U2JsfN0LzFMX5CPrcb+5bAAyqyYURP6Dk/mUIXX87r5x4baQy+juU+ntvf926YA0tR7u6jPRXHymE2axQ/l3NQ==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.4.1", + "@astrojs/internal-helpers": "^0.4.1", "@vercel/analytics": "^1.3.1", "@vercel/edge": "^1.1.2", - "@vercel/nft": "^0.27.3", + "@vercel/nft": "^0.27.4", "esbuild": "^0.21.5", "fast-glob": "^3.3.2", "web-vitals": "^3.5.2" @@ -234,21 +232,22 @@ } }, "node_modules/@astrojs/yaml2ts": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.1.tgz", - "integrity": "sha512-CBaNwDQJz20E5WxzQh4thLVfhB3JEEGz72wRA+oJp6fQR37QLAqXZJU0mHC+yqMOQ6oj0GfRPJrz6hjf+zm6zA==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.2.tgz", + "integrity": "sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==", "license": "MIT", "dependencies": { "yaml": "^2.5.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -256,30 +255,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -304,41 +303,42 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.4.tgz", - "integrity": "sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.4", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -356,28 +356,27 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -387,89 +386,61 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", - "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.4" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -479,12 +450,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -494,16 +465,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", - "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.25.2" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -513,12 +484,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -528,12 +499,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -543,30 +514,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", - "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.4", - "@babel/parser": "^7.25.4", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.4", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -575,32 +546,31 @@ } }, "node_modules/@babel/types": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", - "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@dotcms/client": { - "version": "0.0.1-alpha.33", - "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.33.tgz", - "integrity": "sha512-W9FAJ6eEPiULekE6x5nG99tylKffb2TfybLY17QGhCULfqOr/TYQQGew9kQiwEIszWnqFmMnHzqSYNIsZ0rrkg==", + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.47.tgz", + "integrity": "sha512-rguDpPZJLpAkW9CWhEAaLTjQFsalTSmIzaoI923fzH+Awah0e11uQjTQDZmTHxb0X/wUeGZqUScWaf0KFo/Qxw==", "license": "MIT" }, "node_modules/@dotcms/react": { - "version": "0.0.1-alpha.33", - "resolved": "https://registry.npmjs.org/@dotcms/react/-/react-0.0.1-alpha.33.tgz", - "integrity": "sha512-mkrS44YvFty9mGGHb/YbABb13napXyvfbfTk6b9+eGKrvObRoLlsh3zR0DxrEAhgqvXhZjogfN8YaGYk2fMVdA==", + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/react/-/react-0.0.1-alpha.47.tgz", + "integrity": "sha512-tJfltngGDqaL9IyTDJmD1+cyzAQi2oIW/MBUyzXUhQXHsxsW0YaaVabL7rL2WDVCbEZ0KNi01ySKBOahK4WxhQ==", "license": "MIT", "peerDependencies": { - "@dotcms/client": "0.0.1-alpha.33", + "@dotcms/client": "0.0.1-alpha.47", "@tinymce/tinymce-react": "^5.1.1", "react": ">=18", "react-dom": ">=18" @@ -662,9 +632,9 @@ "license": "MIT" }, "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", "license": "MIT", "optional": true, "dependencies": { @@ -1417,6 +1387,18 @@ "node": ">=12" } }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1440,6 +1422,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -1544,9 +1558,9 @@ } }, "node_modules/@oslojs/encoding": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-0.4.1.tgz", - "integrity": "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", "license": "MIT" }, "node_modules/@pkgjs/parseargs": { @@ -1560,31 +1574,22 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">= 8.0.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz", - "integrity": "sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", + "integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", "cpu": [ "arm" ], @@ -1595,9 +1600,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz", - "integrity": "sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", + "integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", "cpu": [ "arm64" ], @@ -1608,9 +1613,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz", - "integrity": "sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", + "integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", "cpu": [ "arm64" ], @@ -1621,9 +1626,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz", - "integrity": "sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", + "integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", "cpu": [ "x64" ], @@ -1633,10 +1638,36 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", + "integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", + "integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz", - "integrity": "sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", + "integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", "cpu": [ "arm" ], @@ -1647,9 +1678,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz", - "integrity": "sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", + "integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", "cpu": [ "arm" ], @@ -1660,9 +1691,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz", - "integrity": "sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", + "integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", "cpu": [ "arm64" ], @@ -1673,9 +1704,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz", - "integrity": "sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", + "integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", "cpu": [ "arm64" ], @@ -1686,9 +1717,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz", - "integrity": "sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", + "integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", "cpu": [ "ppc64" ], @@ -1699,9 +1730,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz", - "integrity": "sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", + "integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", "cpu": [ "riscv64" ], @@ -1712,9 +1743,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz", - "integrity": "sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", + "integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", "cpu": [ "s390x" ], @@ -1725,9 +1756,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz", - "integrity": "sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", + "integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", "cpu": [ "x64" ], @@ -1738,9 +1769,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz", - "integrity": "sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", + "integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", "cpu": [ "x64" ], @@ -1751,9 +1782,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz", - "integrity": "sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", + "integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", "cpu": [ "arm64" ], @@ -1764,9 +1795,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz", - "integrity": "sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", + "integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", "cpu": [ "ia32" ], @@ -1777,9 +1808,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz", - "integrity": "sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", + "integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", "cpu": [ "x64" ], @@ -1790,14 +1821,56 @@ ] }, "node_modules/@shikijs/core": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.14.1.tgz", - "integrity": "sha512-KyHIIpKNaT20FtFPFjCQB5WVSTpLR/n+jQXhWHWVUMm9MaOaG9BGOG0MSyt7yA4+Lm+4c9rTc03tt3nYzeYSfw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", + "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", + "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.2", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", + "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.2", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/types": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", + "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", "license": "MIT", "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "license": "MIT" + }, "node_modules/@tinymce/tinymce-react": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-5.1.1.tgz", @@ -1870,9 +1943,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, "node_modules/@types/hast": { @@ -1909,15 +1982,15 @@ } }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", - "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -1925,9 +1998,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", "license": "MIT", "dependencies": { "@types/react": "*" @@ -1946,16 +2019,16 @@ "license": "ISC" }, "node_modules/@vercel/analytics": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz", - "integrity": "sha512-xhSlYgAuJ6Q4WQGkzYTLmXwhYl39sWjoMA3nHxfkvG+WdBT25c563a7QhwwKivEOZtPJXifYHR1m2ihoisbWyA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.2.tgz", + "integrity": "sha512-n/Ws7skBbW+fUBMeg+jrT30+GP00jTHvCcL4fuVrShuML0uveEV/4vVUdvqEVnDgXIGfLm0GXW5EID2mCcRXhg==", "license": "MPL-2.0", "dependencies": { "server-only": "^0.0.1" }, "peerDependencies": { "next": ">= 13", - "react": "^18 || ^19" + "react": "^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "next": { @@ -1973,9 +2046,9 @@ "license": "Apache-2.0" }, "node_modules/@vercel/nft": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.27.3.tgz", - "integrity": "sha512-oySTdDSzUAFDXpsSLk9Q943o+/Yu/+TCFxnehpFQEf/3khi2stMpTHPVNwFdvZq/Z4Ky93lE+MGHpXCRpMkSCA==", + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.27.5.tgz", + "integrity": "sha512-b2A7M+4yMHdWKY7xCC+kBEcnMrpaSE84CnuauTjhKKoCEeej0byJMAB8h/RBVnw/HdZOAFVcxR0Izr3LL24FwA==", "license": "MIT", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.5", @@ -1987,7 +2060,7 @@ "estree-walker": "2.0.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "micromatch": "^4.0.2", + "micromatch": "^4.0.8", "node-gyp-build": "^4.2.2", "resolve-from": "^5.0.0" }, @@ -1998,71 +2071,15 @@ "node": ">=16" } }, - "node_modules/@vercel/nft/node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "license": "MIT", - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@vercel/nft/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@vercel/nft/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vercel/nft/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", - "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz", + "integrity": "sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==", "license": "MIT", "dependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-react-jsx-self": "^7.24.5", - "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, @@ -2074,13 +2091,13 @@ } }, "node_modules/@volar/kit": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.0.tgz", - "integrity": "sha512-uqwtPKhrbnP+3f8hs+ltDYXLZ6Wdbs54IzkaPocasI4aBhqWLht5qXctE1MqpZU52wbH359E0u9nhxEFmyon+w==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.8.tgz", + "integrity": "sha512-HY+HTP9sSqj0St9j1N8l85YMu4w0GxCtelzkzZWuq2GVz0+QRYwlyc0mPH7749OknUAdtsdozBR5Ecez55Ncug==", "license": "MIT", "dependencies": { - "@volar/language-service": "2.4.0", - "@volar/typescript": "2.4.0", + "@volar/language-service": "2.4.8", + "@volar/typescript": "2.4.8", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" @@ -2090,23 +2107,23 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0.tgz", - "integrity": "sha512-FTla+khE+sYK0qJP+6hwPAAUwiNHVMph4RUXpxf/FIPKUP61NFrVZorml4mjFShnueR2y9/j8/vnh09YwVdH7A==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.8.tgz", + "integrity": "sha512-K/GxMOXGq997bO00cdFhTNuR85xPxj0BEEAy+BaqqayTmy9Tmhfgmq2wpJcVspRhcwfgPoE2/mEJa26emUhG/g==", "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.0" + "@volar/source-map": "2.4.8" } }, "node_modules/@volar/language-server": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.0.tgz", - "integrity": "sha512-rmGIjAxWekWQiGH97Mosb4juiD/hfFYNQKV5Py9r7vDOLSkbIwRhITbwHm88NJKs8P6TNc6w/PfBXN6yjKadJg==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.8.tgz", + "integrity": "sha512-3Jd9Y+0Zhwi/zfdRxqoNrm7AxP6lgTsw4Ni9r6eCyWYGVsTnpVwGmlcbiZyDja6anoKZxnaeDatX1jkaHHWaRQ==", "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.0", - "@volar/language-service": "2.4.0", - "@volar/typescript": "2.4.0", + "@volar/language-core": "2.4.8", + "@volar/language-service": "2.4.8", + "@volar/typescript": "2.4.8", "path-browserify": "^1.0.1", "request-light": "^0.7.0", "vscode-languageserver": "^9.0.1", @@ -2116,30 +2133,30 @@ } }, "node_modules/@volar/language-service": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.0.tgz", - "integrity": "sha512-4P3yeQXIL68mLfS3n6P3m02IRg3GnLHUU9k/1PCHEfm5FG9bySkDOc72dbBn2vAa2BxOqm18bmmZXrsWuQ5AOw==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.8.tgz", + "integrity": "sha512-9y8X4cdUxXmy4s5HoB8jmOpDIZG7XVFu4iEFvouhZlJX2leCq0pbq5h7dhA+O8My0fne3vtE6cJ4t9nc+8UBZw==", "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.0", + "@volar/language-core": "2.4.8", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" } }, "node_modules/@volar/source-map": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0.tgz", - "integrity": "sha512-2ceY8/NEZvN6F44TXw2qRP6AQsvCYhV2bxaBPWxV9HqIfkbRydSksTFObCF1DBDNBfKiZTS8G/4vqV6cvjdOIQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.8.tgz", + "integrity": "sha512-jeWJBkC/WivdelMwxKkpFL811uH/jJ1kVxa+c7OvG48DXc3VrP7pplSWPP2W1dLMqBxD+awRlg55FQQfiup4cA==", "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0.tgz", - "integrity": "sha512-9zx3lQWgHmVd+JRRAHUSRiEhe4TlzL7U7e6ulWXOxHH/WNYxzKwCvZD7WYWEZFdw4dHfTD9vUR0yPQO6GilCaQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.8.tgz", + "integrity": "sha512-6xkIYJ5xxghVBhVywMoPMidDDAFT1OoQeXwa27HSgJ6AiIKRe61RXLoik+14Z7r0JvnblXVsjsRLmCr42SGzqg==", "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.0", + "@volar/language-core": "2.4.8", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } @@ -2176,9 +2193,9 @@ "license": "ISC" }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2233,15 +2250,6 @@ "string-width": "^4.1.0" } }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-align/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2262,40 +2270,25 @@ "node": ">=8" } }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/any-promise": { @@ -2350,12 +2343,12 @@ "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "license": "Apache-2.0", - "dependencies": { - "dequal": "^2.0.3" + "engines": { + "node": ">= 0.4" } }, "node_modules/array-iterate": { @@ -2369,44 +2362,40 @@ } }, "node_modules/astro": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/astro/-/astro-4.14.4.tgz", - "integrity": "sha512-gpHGyY9qVJg1WXD/0UFoV3cdGZifhmCkJ3fuYV1zUlh+lWbjEB7/cE+KoSvj6aXHJGyLuTbvWOoxZs2yAdnREw==", + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-4.16.8.tgz", + "integrity": "sha512-BRWFP0UQ8gkOr90KQW7oooedtgCk/j91pyv1WQUmgZwMUZk/v0HJRiddAZgvGCECOnmZFc9ZqRZnBsAMUgApNQ==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.10.3", "@astrojs/internal-helpers": "0.4.1", - "@astrojs/markdown-remark": "5.2.0", + "@astrojs/markdown-remark": "5.3.0", "@astrojs/telemetry": "3.1.0", - "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/traverse": "^7.25.3", - "@babel/types": "^7.25.2", - "@oslojs/encoding": "^0.4.1", - "@rollup/pluginutils": "^5.1.0", + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/types": "^7.26.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.1.3", "@types/babel__core": "^7.20.5", "@types/cookie": "^0.6.0", - "acorn": "^8.12.1", - "aria-query": "^5.3.0", + "acorn": "^8.14.0", + "aria-query": "^5.3.2", "axobject-query": "^4.1.0", - "boxen": "7.1.1", + "boxen": "8.0.1", "ci-info": "^4.0.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", - "cookie": "^0.6.0", + "cookie": "^0.7.2", "cssesc": "^3.0.0", - "debug": "^4.3.6", + "debug": "^4.3.7", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.0.0", + "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", - "dset": "^3.1.3", + "dset": "^3.1.4", "es-module-lexer": "^1.5.4", "esbuild": "^0.21.5", "estree-walker": "^3.0.3", - "execa": "^8.0.1", "fast-glob": "^3.3.2", "flattie": "^1.1.1", "github-slugger": "^2.0.0", @@ -2415,31 +2404,30 @@ "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", - "magic-string": "^0.30.11", - "micromatch": "^4.0.7", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "micromatch": "^4.0.8", "mrmime": "^2.0.0", "neotraverse": "^0.6.18", - "ora": "^8.0.1", + "ora": "^8.1.0", "p-limit": "^6.1.0", "p-queue": "^8.0.1", - "path-to-regexp": "^6.2.2", "preferred-pm": "^4.0.0", "prompts": "^2.4.2", - "rehype": "^13.0.1", + "rehype": "^13.0.2", "semver": "^7.6.3", - "shiki": "^1.14.1", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "tsconfck": "^3.1.1", + "shiki": "^1.22.2", + "tinyexec": "^0.3.1", + "tsconfck": "^3.1.4", "unist-util-visit": "^5.0.0", - "vfile": "^6.0.2", - "vite": "^5.4.1", - "vitefu": "^0.2.5", + "vfile": "^6.0.3", + "vite": "^5.4.10", + "vitefu": "^1.0.3", "which-pm": "^3.0.0", "xxhash-wasm": "^1.0.2", "yargs-parser": "^21.1.1", "zod": "^3.23.8", - "zod-to-json-schema": "^3.23.2", + "zod-to-json-schema": "^3.23.5", "zod-to-ts": "^1.2.0" }, "bin": { @@ -2454,6 +2442,34 @@ "sharp": "^0.33.3" } }, + "node_modules/astro/node_modules/@rollup/pluginutils": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/astro/node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, "node_modules/astro/node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2463,6 +2479,18 @@ "@types/estree": "^1.0.0" } }, + "node_modules/astro/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/async-sema": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", @@ -2559,69 +2587,35 @@ } }, "node_modules/boxen": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", - "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", - "camelcase": "^7.0.1", - "chalk": "^5.2.0", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/boxen/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -2637,9 +2631,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -2656,10 +2650,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2669,12 +2663,12 @@ } }, "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2690,9 +2684,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "funding": [ { "type": "opencollective", @@ -2720,17 +2714,15 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, "engines": { - "node": ">=4" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/character-entities": { @@ -2764,27 +2756,18 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" } }, "node_modules/chownr": { @@ -2824,15 +2807,15 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2864,15 +2847,6 @@ "node": ">=12" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2888,24 +2862,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cliui/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cliui/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2926,18 +2882,6 @@ "node": ">=8" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -2979,18 +2923,21 @@ } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/color-string": { @@ -3013,26 +2960,6 @@ "color-support": "bin.js" } }, - "node_modules/color/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT", - "optional": true - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -3077,9 +3004,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3118,12 +3045,12 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3184,9 +3111,9 @@ } }, "node_modules/devalue": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz", - "integrity": "sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", "license": "MIT" }, "node_modules/devlop": { @@ -3224,9 +3151,9 @@ "license": "MIT" }, "node_modules/dset": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", - "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", "license": "MIT", "engines": { "node": ">=4" @@ -3239,15 +3166,15 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "license": "ISC" }, "node_modules/emmet": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.7.tgz", - "integrity": "sha512-O5O5QNqtdlnQM2bmKHtJgyChcrFMgQuulI+WdiOw2NArzprUqqxUW6bgYtKvzKgrsYpuLWalOkdhNP+1jluhCA==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.11.tgz", + "integrity": "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==", "license": "MIT", "workspaces": [ "./packages/scanner", @@ -3261,9 +3188,9 @@ } }, "node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "license": "MIT" }, "node_modules/entities": { @@ -3323,21 +3250,24 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/esprima": { @@ -3365,29 +3295,6 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3429,10 +3336,10 @@ } }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "license": "MIT" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" }, "node_modules/fastq": { "version": "1.17.1", @@ -3521,6 +3428,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3614,27 +3533,12 @@ "node": ">=10" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/gauge/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, "node_modules/gauge/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3649,18 +3553,6 @@ "node": ">=8" } }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3680,9 +3572,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "license": "MIT", "engines": { "node": ">=18" @@ -3691,18 +3583,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/github-slugger": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", @@ -3710,20 +3590,21 @@ "license": "ISC" }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -3793,15 +3674,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3821,9 +3693,9 @@ } }, "node_modules/hast-util-from-html": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.2.tgz", - "integrity": "sha512-HwOHwxdt2zC5KQ/CNoybBntRook2zJvfZE/u5/Ap7aLPe22bDqen7KwGkOqOyzL5zIqKwiYX/OTtE0FWgr6XXA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -3910,16 +3782,15 @@ } }, "node_modules/hast-util-to-html": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.1.tgz", - "integrity": "sha512-hZOofyZANbyWo+9RP75xIDV/gq+OUKx+T46IlwERnKmfpwp81XBFbT9mi26ws+SJchA4RVUQwIBJpqEOBhMzEQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", - "hast-util-raw": "^9.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", @@ -4033,15 +3904,6 @@ "node": ">= 6" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, "node_modules/import-meta-resolve": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", @@ -4208,22 +4070,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "license": "MIT", "engines": { "node": ">=18" @@ -4296,15 +4146,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-schema-traverse": { @@ -4447,18 +4297,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/log-symbols/node_modules/is-unicode-supported": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", @@ -4503,14 +4341,25 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4536,9 +4385,9 @@ } }, "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", "license": "MIT", "funding": { "type": "github", @@ -4576,22 +4425,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4749,9 +4586,9 @@ } }, "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.1.tgz", + "integrity": "sha512-OrkcCoqAkEg9b1ykXBrA0ehRc8H4fGU/03cACmW2xXzau1+dIdS+qJugh1Cqex3hMumSBgSE/5pc7uqP12nLAw==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4759,6 +4596,7 @@ "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" @@ -4781,12 +4619,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5360,9 +5192,9 @@ "license": "MIT" }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5372,40 +5204,37 @@ "node": ">=8.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "license": "ISC", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8" } }, "node_modules/minizlib": { @@ -5461,9 +5290,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/muggle-string": { @@ -5544,9 +5373,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "license": "MIT", "bin": { "node-gyp-build": "bin.js", @@ -5593,33 +5422,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -5661,34 +5463,46 @@ } }, "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "license": "MIT", + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/ora": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", - "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz", + "integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==", "license": "MIT", "dependencies": { "chalk": "^5.3.0", - "cli-cursor": "^4.0.0", + "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.1", - "string-width": "^7.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", "strip-ansi": "^7.1.0" }, "engines": { @@ -5698,16 +5512,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/p-limit": { @@ -5769,9 +5598,9 @@ } }, "node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.3.tgz", + "integrity": "sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==", "license": "MIT", "engines": { "node": ">=14.16" @@ -5790,9 +5619,9 @@ } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, "node_modules/parse-latin": { @@ -5814,12 +5643,12 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -5886,16 +5715,10 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, - "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", - "license": "MIT" - }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -5941,9 +5764,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "funding": [ { "type": "opencollective", @@ -5961,8 +5784,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -6266,21 +6089,28 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, + "node_modules/regex": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "license": "MIT" + }, "node_modules/rehype": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.1.tgz", - "integrity": "sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6294,9 +6124,9 @@ } }, "node_modules/rehype-parse": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz", - "integrity": "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6324,9 +6154,9 @@ } }, "node_modules/rehype-stringify": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.0.tgz", - "integrity": "sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6373,9 +6203,9 @@ } }, "node_modules/remark-rehype": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", - "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6470,51 +6300,33 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, "node_modules/retext": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", @@ -6547,9 +6359,9 @@ } }, "node_modules/retext-smartypants": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.1.0.tgz", - "integrity": "sha512-LDPXg95346bqFZnDMHo0S7Rq5p64+B+N8Vz733+wPMDtwb9rCOs9LIdIEhrUOU+TAywX9St+ocQWJt8wrzivcQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -6602,56 +6414,13 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/rollup": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz", - "integrity": "sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", + "integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -6661,22 +6430,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.0", - "@rollup/rollup-android-arm64": "4.21.0", - "@rollup/rollup-darwin-arm64": "4.21.0", - "@rollup/rollup-darwin-x64": "4.21.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.0", - "@rollup/rollup-linux-arm-musleabihf": "4.21.0", - "@rollup/rollup-linux-arm64-gnu": "4.21.0", - "@rollup/rollup-linux-arm64-musl": "4.21.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.0", - "@rollup/rollup-linux-riscv64-gnu": "4.21.0", - "@rollup/rollup-linux-s390x-gnu": "4.21.0", - "@rollup/rollup-linux-x64-gnu": "4.21.0", - "@rollup/rollup-linux-x64-musl": "4.21.0", - "@rollup/rollup-win32-arm64-msvc": "4.21.0", - "@rollup/rollup-win32-ia32-msvc": "4.21.0", - "@rollup/rollup-win32-x64-msvc": "4.21.0", + "@rollup/rollup-android-arm-eabi": "4.24.3", + "@rollup/rollup-android-arm64": "4.24.3", + "@rollup/rollup-darwin-arm64": "4.24.3", + "@rollup/rollup-darwin-x64": "4.24.3", + "@rollup/rollup-freebsd-arm64": "4.24.3", + "@rollup/rollup-freebsd-x64": "4.24.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.3", + "@rollup/rollup-linux-arm-musleabihf": "4.24.3", + "@rollup/rollup-linux-arm64-gnu": "4.24.3", + "@rollup/rollup-linux-arm64-musl": "4.24.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", + "@rollup/rollup-linux-riscv64-gnu": "4.24.3", + "@rollup/rollup-linux-s390x-gnu": "4.24.3", + "@rollup/rollup-linux-x64-gnu": "4.24.3", + "@rollup/rollup-linux-x64-musl": "4.24.3", + "@rollup/rollup-win32-arm64-msvc": "4.24.3", + "@rollup/rollup-win32-ia32-msvc": "4.24.3", + "@rollup/rollup-win32-x64-msvc": "4.24.3", "fsevents": "~2.3.2" } }, @@ -6848,26 +6619,24 @@ } }, "node_modules/shiki": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.14.1.tgz", - "integrity": "sha512-FujAN40NEejeXdzPt+3sZ3F2dx1U24BY2XTY01+MG8mbxCiA2XukXdcbyMyLAHJ/1AUUnQd1tZlvIjefWWEJeA==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", + "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", "license": "MIT", "dependencies": { - "@shikijs/core": "1.14.1", + "@shikijs/core": "1.22.2", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", + "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/simple-swizzle": { "version": "0.2.2", @@ -6886,9 +6655,9 @@ "license": "MIT" }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6963,31 +6732,37 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/stringify-entities": { @@ -7005,18 +6780,15 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-ansi-cjs": { @@ -7032,15 +6804,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -7059,18 +6822,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -7093,6 +6844,59 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/suf-log": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/suf-log/-/suf-log-2.5.3.tgz", @@ -7103,18 +6907,6 @@ "s.color": "0.0.15" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -7128,9 +6920,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -7164,6 +6956,42 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/tailwindcss/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -7185,6 +7013,18 @@ "node": ">=10" } }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -7202,15 +7042,6 @@ "node": ">=10" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "engines": { - "node": ">=8" - } - }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -7238,22 +7069,19 @@ "node": ">=0.8" } }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "license": "MIT" + }, "node_modules/tinymce": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.3.0.tgz", - "integrity": "sha512-Ls4PgYlpk73XAxBSBqbVmSl8Mb3DuNfgF01GZ0lY6/MOEVRl3IL+VxC1Oe6165e8WqbqVsxO3Qj/PmoYNvQKGQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.4.1.tgz", + "integrity": "sha512-g1Ieaio5YU+jLEQZkQyxTT8EY/im+TC/CFBPlqDBCNdsF8YQOeLMot+K6vmFOAXhNc85KhP1rC9Dn2X+iBFDGg==", "license": "GPL-2.0-or-later", "peer": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7299,9 +7127,9 @@ "license": "Apache-2.0" }, "node_modules/tsconfck": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.1.tgz", - "integrity": "sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.4.tgz", + "integrity": "sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==", "license": "MIT", "bin": { "tsconfck": "bin/tsconfck.js" @@ -7319,19 +7147,19 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD", "optional": true }, "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=12.20" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7344,9 +7172,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -7357,9 +7185,9 @@ } }, "node_modules/typescript-auto-import-cache": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.3.tgz", - "integrity": "sha512-ojEC7+Ci1ij9eE6hp8Jl9VUNnsEKzztktP5gtYNRMrTmfXVwA1PITYYAkpxCvvupdSYa/Re51B6KMcv1CTZEUA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.5.tgz", + "integrity": "sha512-fAIveQKsoYj55CozUiBoj4b/7WpN0i4o74wiGY5JVUEoD0XiqDk1tJqTEjgzL2/AizKQrXxyRosSebyDzBZKjw==", "license": "MIT", "dependencies": { "semver": "^7.3.8" @@ -7514,9 +7342,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -7533,8 +7361,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -7550,13 +7378,12 @@ "license": "MIT" }, "node_modules/vfile": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", - "integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" }, "funding": { @@ -7593,13 +7420,13 @@ } }, "node_modules/vite": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", - "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", "license": "MIT", "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.41", + "postcss": "^8.4.43", "rollup": "^4.20.0" }, "bin": { @@ -7652,12 +7479,16 @@ } }, "node_modules/vitefu": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", - "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.3.tgz", + "integrity": "sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==", "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*" + ], "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0" }, "peerDependenciesMeta": { "vite": { @@ -7666,9 +7497,9 @@ } }, "node_modules/volar-service-css": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.61.tgz", - "integrity": "sha512-Ct9L/w+IB1JU8F4jofcNCGoHy6TF83aiapfZq9A0qYYpq+Kk5dH+ONS+rVZSsuhsunq8UvAuF8Gk6B8IFLfniw==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.62.tgz", + "integrity": "sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==", "license": "MIT", "dependencies": { "vscode-css-languageservice": "^6.3.0", @@ -7685,9 +7516,9 @@ } }, "node_modules/volar-service-emmet": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.61.tgz", - "integrity": "sha512-iiYqBxjjcekqrRruw4COQHZME6EZYWVbkHjHDbULpml3g8HGJHzpAMkj9tXNCPxf36A+f1oUYjsvZt36qPg4cg==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.62.tgz", + "integrity": "sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==", "license": "MIT", "dependencies": { "@emmetio/css-parser": "^0.4.0", @@ -7705,9 +7536,9 @@ } }, "node_modules/volar-service-html": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.61.tgz", - "integrity": "sha512-yFE+YmmgqIL5HI4ORqP++IYb1QaGcv+xBboI0WkCxJJ/M35HZj7f5rbT3eQ24ECLXFbFCFanckwyWJVz5KmN3Q==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.62.tgz", + "integrity": "sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==", "license": "MIT", "dependencies": { "vscode-html-languageservice": "^5.3.0", @@ -7724,9 +7555,9 @@ } }, "node_modules/volar-service-prettier": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.61.tgz", - "integrity": "sha512-F612nql5I0IS8HxXemCGvOR2Uxd4XooIwqYVUvk7WSBxP/+xu1jYvE3QJ7EVpl8Ty3S4SxPXYiYTsG3bi+gzIQ==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.62.tgz", + "integrity": "sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==", "license": "MIT", "dependencies": { "vscode-uri": "^3.0.8" @@ -7745,9 +7576,9 @@ } }, "node_modules/volar-service-typescript": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.61.tgz", - "integrity": "sha512-4kRHxVbW7wFBHZWRU6yWxTgiKETBDIJNwmJUAWeP0mHaKpnDGj/astdRFKqGFRYVeEYl45lcUPhdJyrzanjsdQ==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.62.tgz", + "integrity": "sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==", "license": "MIT", "dependencies": { "path-browserify": "^1.0.1", @@ -7767,9 +7598,9 @@ } }, "node_modules/volar-service-typescript-twoslash-queries": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.61.tgz", - "integrity": "sha512-99FICGrEF0r1E2tV+SvprHPw9Knyg7BdW2fUch0tf59kG+KG+Tj4tL6tUg+cy8f23O/VXlmsWFMIE+bx1dXPnQ==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.62.tgz", + "integrity": "sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==", "license": "MIT", "dependencies": { "vscode-uri": "^3.0.8" @@ -7784,9 +7615,9 @@ } }, "node_modules/volar-service-yaml": { - "version": "0.0.61", - "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.61.tgz", - "integrity": "sha512-L+gbDiLDQQ1rZUbJ3mf3doDsoQUa8OZM/xdpk/unMg1Vz24Zmi2Ign8GrZyBD7bRoIQDwOH9gdktGDKzRPpUNw==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.62.tgz", + "integrity": "sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==", "license": "MIT", "dependencies": { "vscode-uri": "^3.0.8", @@ -7802,25 +7633,25 @@ } }, "node_modules/vscode-css-languageservice": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.0.tgz", - "integrity": "sha512-nU92imtkgzpCL0xikrIb8WvedV553F2BENzgz23wFuok/HLN5BeQmroMy26pUwFxV2eV8oNRmYCUv8iO7kSMhw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.1.tgz", + "integrity": "sha512-1BzTBuJfwMc3A0uX4JBdJgoxp74cjj4q2mDJdp49yD/GuAq4X0k5WtK6fNcMYr+FfJ9nqgR6lpfCSZDkARJ5qQ==", "license": "MIT", "dependencies": { "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.11", + "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.0.8" } }, "node_modules/vscode-html-languageservice": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.0.tgz", - "integrity": "sha512-C4Z3KsP5Ih+fjHpiBc5jxmvCl+4iEwvXegIrzu2F5pktbWvQaBT3YkVPk8N+QlSSMk8oCG6PKtZ/Sq2YHb5e8g==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.1.tgz", + "integrity": "sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==", "license": "MIT", "dependencies": { "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.11", + "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.0.8" } @@ -7979,15 +7810,6 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wide-align/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8008,68 +7830,33 @@ "node": ">=8" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "license": "MIT", - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "string-width": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -8093,15 +7880,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -8117,24 +7895,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8155,51 +7915,31 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -8230,9 +7970,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -8360,15 +8100,6 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8389,18 +8120,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yocto-queue": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", @@ -8423,9 +8142,9 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.2.tgz", - "integrity": "sha512-uSt90Gzc/tUfyNqxnjlfBs8W6WSGpNBv0rVsNxP/BVSMHMKGdthPYff4xtCHYloJGM0CFxFsb3NbC0eqPhfImw==", + "version": "3.23.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.5.tgz", + "integrity": "sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==", "license": "ISC", "peerDependencies": { "zod": "^3.23.3" diff --git a/examples/astro/src/react/hooks/usePageAsset.ts b/examples/astro/src/react/hooks/usePageAsset.ts index d0cd3242a32a..2703e66568f2 100644 --- a/examples/astro/src/react/hooks/usePageAsset.ts +++ b/examples/astro/src/react/hooks/usePageAsset.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { - CUSTOMER_ACTIONS, + CLIENT_ACTIONS, isInsideEditor, postMessageToEditor, } from "@dotcms/client"; @@ -24,7 +24,7 @@ export const usePageAsset = (currentPageAsset: DotCMSPageAsset | undefined) => { // If the page is not found, let the editor know if (!currentPageAsset) { - postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY }); + postMessageToEditor({ action: CLIENT_ACTIONS.CLIENT_READY }); return; } diff --git a/examples/nextjs/package-lock.json b/examples/nextjs/package-lock.json index da568569dd8f..37a99577f414 100644 --- a/examples/nextjs/package-lock.json +++ b/examples/nextjs/package-lock.json @@ -11,7 +11,7 @@ "@dotcms/client": "latest", "@dotcms/experiments": "latest", "@dotcms/react": "latest", - "next": "14.1.1", + "next": "^14.2.16", "react": "^18", "react-dom": "^18" }, @@ -29,6 +29,7 @@ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -36,67 +37,63 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@dotcms/client": { - "version": "0.0.1-alpha.34", - "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.34.tgz", - "integrity": "sha512-j+kYjNCqkZzK6yW5Wwv737WpiiHVfPMYFyYFh8KeBBj1Hh2WIMGZjP/8EGfGNw/13QPWYlhKfK1f4P/ctZwO8w==" + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.47.tgz", + "integrity": "sha512-rguDpPZJLpAkW9CWhEAaLTjQFsalTSmIzaoI923fzH+Awah0e11uQjTQDZmTHxb0X/wUeGZqUScWaf0KFo/Qxw==", + "license": "MIT" }, "node_modules/@dotcms/experiments": { - "version": "0.0.1-alpha.34", - "resolved": "https://registry.npmjs.org/@dotcms/experiments/-/experiments-0.0.1-alpha.34.tgz", - "integrity": "sha512-Q5oQSbh/OxoH6heeE06C8Zm1qOYcHDDatxURHKjaoEjNQABA08Ar+xdVMNomYI8SzlQLT4MJRCoJ/JR/B1L4HA==", + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/experiments/-/experiments-0.0.1-alpha.47.tgz", + "integrity": "sha512-gg/oXx6zjcaL8izmmdEJUFZCSdV2zFbf7YZnvev1gEYm8bDnjx/BA6XwijOFb+ACrJmhAYMyBe3JEw+xd2moYQ==", + "license": "MIT", "dependencies": { "@jitsu/sdk-js": "^3.1.5" }, "peerDependencies": { - "@dotcms/client": "0.0.1-alpha.34", + "@dotcms/client": "0.0.1-alpha.47", "react": ">=18", "react-dom": ">=18" } }, "node_modules/@dotcms/react": { - "version": "0.0.1-alpha.34", - "resolved": "https://registry.npmjs.org/@dotcms/react/-/react-0.0.1-alpha.34.tgz", - "integrity": "sha512-WvFvjqV5iBi8gyF+wawgvsVCmF1/rhye+xQR4N3CMyYx6Dlltjc2bKWkUkOTez6vSH2FGW80Gd1k3FtJibbyyw==", + "version": "0.0.1-alpha.47", + "resolved": "https://registry.npmjs.org/@dotcms/react/-/react-0.0.1-alpha.47.tgz", + "integrity": "sha512-tJfltngGDqaL9IyTDJmD1+cyzAQi2oIW/MBUyzXUhQXHsxsW0YaaVabL7rL2WDVCbEZ0KNi01ySKBOahK4WxhQ==", + "license": "MIT", "peerDependencies": { - "@dotcms/client": "0.0.1-alpha.34", + "@dotcms/client": "0.0.1-alpha.47", "@tinymce/tinymce-react": "^5.1.1", "react": ">=18", "react-dom": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -106,6 +103,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -125,21 +123,24 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -152,6 +153,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -164,13 +166,16 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -184,10 +189,11 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -200,6 +206,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -214,13 +221,15 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/@jitsu/sdk-js/-/sdk-js-3.1.5.tgz", "integrity": "sha512-e7P8uvGBNwWCC864MItcYSv0IT2+nwYiX8QXZ0lfyG8hutEXXX9Yt2/+MynXuGxMIoIrJ+j0bWVu20k9rrhxSg==", - "deprecated": "This package is for legacy Jitsu Classic version. For latest version of Jitsu please use @jitsu/js" + "deprecated": "This package is for legacy Jitsu Classic version. For latest version of Jitsu please use @jitsu/js", + "license": "MIT" }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -235,6 +244,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -244,47 +254,53 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@next/env": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.1.tgz", - "integrity": "sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==" + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.16.tgz", + "integrity": "sha512-fLrX5TfJzHCbnZ9YUSnGW63tMV3L4nSfhgOQ0iCcX21Pt+VSTDuaLsSuL8J/2XAiVA5AnzvXDpf6pMs60QxOag==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { "version": "14.0.4", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz", "integrity": "sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==", "dev": true, + "license": "MIT", "dependencies": { "glob": "7.1.7" } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.1.tgz", - "integrity": "sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.16.tgz", + "integrity": "sha512-uFT34QojYkf0+nn6MEZ4gIWQ5aqGF11uIZ1HSxG+cSbj+Mg3+tYm8qXYd3dKN5jqKUm5rBVvf1PBRO/MeQ6rxw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -294,12 +310,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.1.tgz", - "integrity": "sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.16.tgz", + "integrity": "sha512-mCecsFkYezem0QiZlg2bau3Xul77VxUD38b/auAjohMA22G9KTJneUYMv78vWoCCFkleFAhY1NIvbyjj1ncG9g==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -309,12 +326,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.1.tgz", - "integrity": "sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.16.tgz", + "integrity": "sha512-yhkNA36+ECTC91KSyZcgWgKrYIyDnXZj8PqtJ+c2pMvj45xf7y/HrgI17hLdrcYamLfVt7pBaJUMxADtPaczHA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -324,12 +342,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.1.tgz", - "integrity": "sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.16.tgz", + "integrity": "sha512-X2YSyu5RMys8R2lA0yLMCOCtqFOoLxrq2YbazFvcPOE4i/isubYjkh+JCpRmqYfEuCVltvlo+oGfj/b5T2pKUA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -339,12 +358,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.1.tgz", - "integrity": "sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.16.tgz", + "integrity": "sha512-9AGcX7VAkGbc5zTSa+bjQ757tkjr6C/pKS7OK8cX7QEiK6MHIIezBLcQ7gQqbDW2k5yaqba2aDtaBeyyZh1i6Q==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -354,12 +374,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.1.tgz", - "integrity": "sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.16.tgz", + "integrity": "sha512-Klgeagrdun4WWDaOizdbtIIm8khUDQJ/5cRzdpXHfkbY91LxBXeejL4kbZBrpR/nmgRrQvmz4l3OtttNVkz2Sg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -369,12 +390,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.1.tgz", - "integrity": "sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.16.tgz", + "integrity": "sha512-PwW8A1UC1Y0xIm83G3yFGPiOBftJK4zukTmk7DI1CebyMOoaVpd8aSy7K6GhobzhkjYvqS/QmzcfsWG2Dwizdg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -384,12 +406,13 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.1.tgz", - "integrity": "sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.16.tgz", + "integrity": "sha512-jhPl3nN0oKEshJBNDAo0etGMzv0j3q3VYorTSFqH1o3rwv1MQRdor27u1zhkgsHPNeY1jxcgyx1ZsCkDD1IHgg==", "cpu": [ "ia32" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -399,12 +422,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.1.tgz", - "integrity": "sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.16.tgz", + "integrity": "sha512-OA7NtfxgirCjfqt+02BqxC3MIgM/JaGjw9tOe4fyZgPsqfseNiMPnCRP44Pfs+Gpo9zPN+SXaFsgP6vk8d571A==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -418,6 +442,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -431,6 +456,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -440,6 +466,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -448,34 +475,61 @@ "node": ">= 8" } }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz", - "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==", - "dev": true + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", - "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", "dependencies": { + "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz", - "integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", "dev": true, "license": "MIT", "dependencies": { @@ -485,27 +539,14 @@ "postcss-selector-parser": "6.0.10" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" - } - }, - "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" } }, "node_modules/@tinymce/tinymce-react": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-5.1.1.tgz", "integrity": "sha512-DQ0wpvnf/9z8RsOEAmrWZ1DN1PKqcQHfU+DpM3llLze7FHmxVtzuN8O+FYh0oAAF4stzAXwiCIVacfqjMwRieQ==", + "license": "MIT", "peer": true, "dependencies": { "prop-types": "^15.6.2", @@ -520,13 +561,15 @@ "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/parser": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -555,6 +598,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" @@ -572,6 +616,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, + "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -585,6 +630,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", @@ -613,6 +659,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -622,6 +669,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -637,6 +685,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -653,13 +702,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -672,6 +723,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -681,6 +733,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -697,6 +750,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -706,6 +760,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -720,13 +775,15 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -739,21 +796,24 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/array-buffer-byte-length": { @@ -761,6 +821,7 @@ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -777,6 +838,7 @@ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -797,6 +859,7 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -806,6 +869,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -826,6 +890,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -846,6 +911,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -864,6 +930,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -877,29 +944,21 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { @@ -907,6 +966,7 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -928,12 +988,13 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "dev": true, "funding": [ { @@ -949,12 +1010,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -972,6 +1034,7 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -983,34 +1046,38 @@ } }, "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", "dev": true, + "license": "MPL-2.0", "engines": { "node": ">=4" } }, "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1023,6 +1090,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1033,6 +1101,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1041,9 +1110,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -1059,11 +1128,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1088,6 +1158,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -1107,6 +1178,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1116,14 +1188,15 @@ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001616", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001616.tgz", - "integrity": "sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "funding": [ { "type": "opencollective", @@ -1137,13 +1210,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1160,6 +1235,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1184,6 +1260,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1194,13 +1271,15 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1212,13 +1291,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -1227,13 +1308,15 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1248,6 +1331,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -1259,13 +1343,15 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -1283,6 +1369,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -1300,6 +1387,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -1313,12 +1401,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1333,13 +1422,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -1357,6 +1448,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -1369,26 +1461,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1400,13 +1485,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -1418,25 +1505,29 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.757", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.757.tgz", - "integrity": "sha512-jftDaCknYSSt/+KKeXzH3LX5E2CvRLm75P3Hj+J/dv3CL0qUYcOt13d5FN1NiL5IJbbhzHrb3BomeG2tkSlZmw==", - "dev": true + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -1450,6 +1541,7 @@ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -1510,6 +1602,7 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -1522,15 +1615,17 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -1539,12 +1634,12 @@ "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", + "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" }, "engines": { @@ -1556,6 +1651,7 @@ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -1568,6 +1664,7 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -1582,6 +1679,7 @@ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.0" } @@ -1591,6 +1689,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -1604,10 +1703,11 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1617,6 +1717,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1625,16 +1726,18 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -1684,6 +1787,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.4.tgz", "integrity": "sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==", "dev": true, + "license": "MIT", "dependencies": { "@next/eslint-plugin-next": "14.0.4", "@rushstack/eslint-patch": "^1.3.3", @@ -1710,6 +1814,7 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -1721,22 +1826,25 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", "is-glob": "^4.0.3" }, "engines": { @@ -1747,14 +1855,24 @@ }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*" + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } } }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -1772,39 +1890,43 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -1812,6 +1934,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -1821,6 +1944,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -1833,77 +1957,80 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" }, "engines": { "node": ">=4.0" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1916,6 +2043,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -1928,6 +2056,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -1945,6 +2074,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1954,6 +2084,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -1970,6 +2101,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1982,6 +2114,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -1995,10 +2128,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2011,6 +2145,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2023,6 +2158,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2032,6 +2168,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2040,13 +2177,15 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2063,6 +2202,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2074,19 +2214,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2096,6 +2239,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -2108,6 +2252,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2120,6 +2265,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2136,6 +2282,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -2149,22 +2296,25 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -2181,6 +2331,7 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, + "license": "MIT", "engines": { "node": "*" }, @@ -2193,7 +2344,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2201,6 +2353,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2214,6 +2367,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2223,6 +2377,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2241,6 +2396,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2250,6 +2406,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -2269,6 +2426,7 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -2282,10 +2440,11 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.4.tgz", - "integrity": "sha512-ofbkKj+0pjXjhejr007J/fLf+sW+8H7K5GCm+msC8q3IpvgjobpyPqSRFemNyIMxklC0zeJpi7VDFna19FacvQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -2297,7 +2456,9 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2318,6 +2479,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2330,6 +2492,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -2345,6 +2508,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -2361,6 +2525,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -2381,6 +2546,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -2391,19 +2557,22 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2413,6 +2582,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2422,6 +2592,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -2434,6 +2605,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2446,6 +2618,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2458,6 +2631,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -2473,6 +2647,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -2481,10 +2656,11 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -2494,6 +2670,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2510,6 +2687,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -2518,7 +2696,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2528,13 +2708,15 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -2549,6 +2731,7 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -2565,6 +2748,7 @@ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -2580,6 +2764,7 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -2592,6 +2777,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2604,6 +2790,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -2615,11 +2802,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2628,12 +2826,16 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2644,6 +2846,7 @@ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, + "license": "MIT", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -2659,6 +2862,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -2674,6 +2878,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2683,6 +2888,7 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -2695,6 +2901,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2704,6 +2911,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -2719,6 +2927,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2731,6 +2940,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2743,6 +2953,7 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2755,6 +2966,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2764,6 +2976,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -2779,6 +2992,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2788,6 +3002,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -2804,6 +3019,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2816,6 +3032,7 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -2831,6 +3048,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -2846,6 +3064,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -2861,6 +3080,7 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -2876,6 +3096,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2888,6 +3109,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -2900,6 +3122,7 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" @@ -2915,38 +3138,42 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -2955,10 +3182,11 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -2966,13 +3194,15 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2984,25 +3214,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -3015,6 +3249,7 @@ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -3030,21 +3265,24 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, + "license": "MIT", "dependencies": { "language-subtag-registry": "^0.3.20" }, @@ -3057,6 +3295,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3070,6 +3309,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -3078,13 +3318,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -3113,12 +3355,14 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -3127,33 +3371,30 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } + "license": "ISC" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -3165,6 +3406,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3177,30 +3419,34 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.0.tgz", - "integrity": "sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -3217,6 +3463,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3228,15 +3475,17 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/next": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/next/-/next-14.1.1.tgz", - "integrity": "sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.16.tgz", + "integrity": "sha512-LcO7WnFu6lYSvCzZoo1dB+IO0xXz5uEv52HF1IUN0IqVTUIZGHuuR10I5efiLadGt+4oZqTcNZyVVEem/TM5nA==", + "license": "MIT", "dependencies": { - "@next/env": "14.1.1", - "@swc/helpers": "0.5.2", + "@next/env": "14.2.16", + "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "graceful-fs": "^4.2.11", @@ -3250,18 +3499,19 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.1.1", - "@next/swc-darwin-x64": "14.1.1", - "@next/swc-linux-arm64-gnu": "14.1.1", - "@next/swc-linux-arm64-musl": "14.1.1", - "@next/swc-linux-x64-gnu": "14.1.1", - "@next/swc-linux-x64-musl": "14.1.1", - "@next/swc-win32-arm64-msvc": "14.1.1", - "@next/swc-win32-ia32-msvc": "14.1.1", - "@next/swc-win32-x64-msvc": "14.1.1" + "@next/swc-darwin-arm64": "14.2.16", + "@next/swc-darwin-x64": "14.2.16", + "@next/swc-linux-arm64-gnu": "14.2.16", + "@next/swc-linux-arm64-musl": "14.2.16", + "@next/swc-linux-x64-gnu": "14.2.16", + "@next/swc-linux-x64-musl": "14.2.16", + "@next/swc-win32-arm64-msvc": "14.2.16", + "@next/swc-win32-ia32-msvc": "14.2.16", + "@next/swc-win32-x64-msvc": "14.2.16" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -3270,6 +3520,9 @@ "@opentelemetry/api": { "optional": true }, + "@playwright/test": { + "optional": true + }, "sass": { "optional": true } @@ -3293,6 +3546,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -3303,16 +3557,18 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3322,6 +3578,7 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3330,6 +3587,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3339,15 +3597,20 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3357,6 +3620,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -3366,6 +3630,7 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -3384,6 +3649,7 @@ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3398,6 +3664,7 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3416,6 +3683,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3425,28 +3693,12 @@ "node": ">= 0.4" } }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.values": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3464,6 +3716,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -3473,6 +3726,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -3490,6 +3744,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3505,6 +3760,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -3515,11 +3771,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3532,6 +3796,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3541,6 +3806,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3550,6 +3816,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3558,52 +3825,48 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3616,6 +3879,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3625,6 +3889,7 @@ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -3634,14 +3899,15 @@ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -3657,10 +3923,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -3671,6 +3938,7 @@ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -3688,6 +3956,7 @@ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -3717,6 +3986,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -3738,10 +4008,11 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -3750,29 +4021,51 @@ } }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3785,13 +4078,15 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -3800,6 +4095,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -3811,6 +4107,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3833,12 +4130,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -3850,6 +4149,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -3861,13 +4161,15 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -3877,6 +4179,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -3889,6 +4192,7 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3905,22 +4209,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -3934,6 +4233,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -3951,6 +4251,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3960,6 +4261,7 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -3969,6 +4271,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -3978,7 +4281,9 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -4008,6 +4313,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -4017,6 +4323,7 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -4035,6 +4342,7 @@ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -4051,18 +4359,17 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4075,6 +4382,7 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -4092,6 +4400,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -4107,6 +4416,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4119,6 +4429,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4128,6 +4439,7 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -4146,6 +4458,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -4158,14 +4471,16 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -4183,6 +4498,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -4201,6 +4517,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4214,13 +4531,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4233,6 +4552,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -4243,11 +4563,27 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4269,11 +4605,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4292,6 +4640,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4306,6 +4655,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4323,6 +4673,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4336,6 +4687,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4348,6 +4700,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -4357,6 +4710,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4368,6 +4722,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -4391,6 +4746,7 @@ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -4413,37 +4769,38 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/sucrase/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4459,6 +4816,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -4471,6 +4829,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4479,10 +4838,11 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", - "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "dev": true, + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -4515,11 +4875,26 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4528,13 +4903,15 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -4544,6 +4921,7 @@ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -4552,9 +4930,10 @@ } }, "node_modules/tinymce": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.3.0.tgz", - "integrity": "sha512-Ls4PgYlpk73XAxBSBqbVmSl8Mb3DuNfgF01GZ0lY6/MOEVRl3IL+VxC1Oe6165e8WqbqVsxO3Qj/PmoYNvQKGQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.4.1.tgz", + "integrity": "sha512-g1Ieaio5YU+jLEQZkQyxTT8EY/im+TC/CFBPlqDBCNdsF8YQOeLMot+K6vmFOAXhNc85KhP1rC9Dn2X+iBFDGg==", + "license": "GPL-2.0-or-later", "peer": true }, "node_modules/to-regex-range": { @@ -4562,6 +4941,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4570,10 +4950,11 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -4585,13 +4966,15 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -4600,15 +4983,17 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -4621,6 +5006,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -4633,6 +5019,7 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -4647,6 +5034,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -4666,6 +5054,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -4686,6 +5075,7 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -4702,10 +5092,11 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "tsc": "bin/tsc", @@ -4720,6 +5111,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -4731,9 +5123,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", - "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -4749,9 +5141,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -4765,6 +5158,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -4773,13 +5167,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4795,6 +5191,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -4807,13 +5204,14 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, + "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -4822,8 +5220,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -4837,6 +5235,7 @@ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -4855,6 +5254,7 @@ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -4874,6 +5274,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4883,6 +5284,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -4901,6 +5303,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4917,13 +5320,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4934,10 +5339,11 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4950,6 +5356,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4962,6 +5369,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -4976,19 +5384,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yaml": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", - "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -5001,6 +5405,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 060c1f9f8164..d7894ffd15dd 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@dotcms/client": "latest", - "@dotcms/react": "latest", "@dotcms/experiments": "latest", - "next": "14.1.1", + "@dotcms/react": "latest", + "next": "^14.2.16", "react": "^18", "react-dom": "^18" }, diff --git a/examples/nextjs/src/hooks/usePageAsset.js b/examples/nextjs/src/hooks/usePageAsset.js index dca69d7e7565..c67553920274 100644 --- a/examples/nextjs/src/hooks/usePageAsset.js +++ b/examples/nextjs/src/hooks/usePageAsset.js @@ -1,11 +1,7 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState } from 'react'; -import { client } from "@/utils/dotcmsClient"; -import { - CUSTOMER_ACTIONS, - isInsideEditor, - postMessageToEditor, -} from "@dotcms/client"; +import { client } from '@/utils/dotcmsClient'; +import { CLIENT_ACTIONS, isInsideEditor, postMessageToEditor } from '@dotcms/client'; export const usePageAsset = (currentPageAsset) => { const [pageAsset, setPageAsset] = useState(null); @@ -15,7 +11,7 @@ export const usePageAsset = (currentPageAsset) => { return; } - client.editor.on("changes", (page) => { + client.editor.on('changes', (page) => { if (!page) { return; } @@ -25,13 +21,13 @@ export const usePageAsset = (currentPageAsset) => { // If the page is not found, let the editor know if (!currentPageAsset) { - postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY }); + postMessageToEditor({ action: CLIENT_ACTIONS.CLIENT_READY }); return; } return () => { - client.editor.off("changes"); + client.editor.off('changes'); }; }, [currentPageAsset]);