diff --git a/.eslintrc b/.eslintrc.json similarity index 56% rename from .eslintrc rename to .eslintrc.json index 8c837062..7fb8484f 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -8,12 +8,19 @@ "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/eslint-recommended", "prettier", - "plugin:nuxt/recommended" + "plugin:nuxt/recommended", + "plugin:@conarti/feature-sliced/recommended" ], "parser": "vue-eslint-parser", "plugins": ["@typescript-eslint"], "root": true, - "ignorePatterns": ["package.json", "postcss.config.js","tailwind.config.js", "vendor/"], + "ignorePatterns": [ + "package.json", + "postcss.config.js", + "tailwind.config.js", + "src/shared/lib/vendor/", + "src/.eslintrc.json" + ], "parserOptions": { "project": "./tsconfig.json", "extraFileExtensions": [".vue"], @@ -24,10 +31,14 @@ }, "rules": { "import/prefer-default-export": "off", - "no-console": ["error", { "allow": ["info","warn", "error"] }], - "vue/component-name-in-template-casing": ["error", "PascalCase", { - "registeredComponentsOnly": true, - "ignores": [] - }] + "no-console": ["error", { "allow": ["info", "warn", "error"] }], + "vue/component-name-in-template-casing": [ + "error", + "PascalCase", + { + "registeredComponentsOnly": true, + "ignores": [] + } + ] } } diff --git a/.storybook/main.ts b/.storybook/main.ts index f6318872..8d9f1cb3 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -10,6 +10,7 @@ module.exports = { "../components/**/*.stories.@(js|jsx|ts|tsx)", "../layouts/**/*.stories.@(js|jsx|ts|tsx)", "../pages/**/*.stories.@(js|jsx|ts|tsx)", + "../src/**/**/**/*.stories.@(js|jsx|ts|tsx)", ], addons: [ "@storybook/addon-links", @@ -67,7 +68,7 @@ module.exports = { }; }, env: (config) => { - const iconComponentFolder = path.resolve(__dirname, '../components/IconSvg'); + const iconComponentFolder = path.resolve(__dirname, '../src/shared/ui/icon-svg/icon-svg-originals'); const allIconNamesList = !fs.existsSync(iconComponentFolder) ? [] : fs diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 9a745514..49ef5e70 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -3,7 +3,7 @@ import {addParameters, app} from '@storybook/vue3'; import "../assets/index.css"; import "../assets/index"; import "./stories.css" -import SfdumpWrap from "../vendor/dumper"; +import SfdumpWrap from "~/src/shared/lib/vendor/dumper"; addParameters({ actions: {argTypesRegex: "^on[A-Z].*"}, diff --git a/README.md b/README.md index c287f714..bedff026 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,14 @@ Welcome to the official repository for the Buggregator Frontend Single Page Application (SPA), a crucial component of the Buggregator. This repository focuses exclusively on the frontend aspect of Buggregator, developed using Nuxt.js framework and enriched with Storybook for an enhanced component-driven development experience. - ## Overview -Buggregator is a comprehensive, lightweight server designed for debugging applications written on PHP, JS, etc. This repository is tailored to work seamlessly with the Buggregator server, providing a user-friendly interface and interactive features that make debugging more efficient and less cumbersome. +Buggregator is a comprehensive, lightweight server designed for debugging applications written on PHP, JS, etc. This repository is tailored to work seamlessly with the Buggregator server, providing a user-friendly interface and interactive features that make debugging more efficient and less cumbersome. ## Contribution + Contributions to the Buggregator Frontend SPA are always welcome. Whether it's fixing bugs, improving documentation, or suggesting new features, your input is valuable. Please read our contribution guidelines before submitting your pull request. ## Support + If you encounter any issues or have questions, feel free to open an issue in this repository. For more detailed discussions or support, join our community on [Discord](https://discord.gg/FTpBM7xU). diff --git a/assets/vue3-tabs-component.scss b/assets/vue3-tabs-component.scss index 2e39f213..102aa8a6 100644 --- a/assets/vue3-tabs-component.scss +++ b/assets/vue3-tabs-component.scss @@ -25,7 +25,3 @@ .tabs-component-panel { } - -.preview-tab-badge { - @apply bg-red-800 ml-2 text-2xs px-2 py-1 rounded text-white uppercase; -} diff --git a/components/CodeSnippet/CodeSnippet.vue b/components/CodeSnippet/CodeSnippet.vue deleted file mode 100644 index b480e6a9..00000000 --- a/components/CodeSnippet/CodeSnippet.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - - - diff --git a/components/EventTable/EventTable.stories.ts b/components/EventTable/EventTable.stories.ts deleted file mode 100644 index e9ac70db..00000000 --- a/components/EventTable/EventTable.stories.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import EventTable from "~/components/EventTable/EventTable.vue"; -import EventTableRow from "~/components/EventTableRow/EventTableRow.vue"; - -export default { - title: "Components/EventTable", - component: EventTable -} as Meta; - -const TableTemplate: Story = (args) => ({ - components: { EventTable, EventTableRow }, - setup() { - return { - args, - }; - }, - template: ` - - This is a row 1 - - - This is a row 2 - - - This is a row 3 - - `, -}); - -export const Table = TableTemplate.bind({}); -Table.args = {}; diff --git a/components/EventTableRow/EventTableRow.stories.ts b/components/EventTableRow/EventTableRow.stories.ts deleted file mode 100644 index 58442f69..00000000 --- a/components/EventTableRow/EventTableRow.stories.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import EventTableRow from "~/components/EventTableRow/EventTableRow.vue"; - -export default { - title: "Components/EventTableRow", - component: EventTableRow -} as Meta; - -const Template: Story = (args) => ({ - components: { EventTableRow }, - setup() { - return { - args, - }; - }, - template: ` - This is a row 1 - `, -}); - -export const TableRow = Template.bind({}); -TableRow.args = { - title: "Row 1", -}; diff --git a/components/EventTableRow/EventTableRow.vue b/components/EventTableRow/EventTableRow.vue deleted file mode 100644 index 41568aef..00000000 --- a/components/EventTableRow/EventTableRow.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - - - diff --git a/components/FileView/FileView.stories.ts b/components/FileView/FileView.stories.ts deleted file mode 100644 index f0dce96b..00000000 --- a/components/FileView/FileView.stories.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import FileView from "~/components/FileView/FileView.vue"; - -export default { - title: "Components/FileView", - component: FileView -} as Meta; - -const Template: Story = (args) => ({ - components: { FileView }, - setup() { - return { - args, - }; - }, - template: ` - This is a row 1 - `, -}); - -export const FileDefault = Template.bind({}); -FileDefault.args = { - file: { - file_name: "/root/repos/buggreagtor/examples/app/Modules/Ray/RayCommon.php", - line_number: 96, - class: "App\\Http\\Controllers\\CallAction", - method: "rayTrace", - vendor_frame: false, - } -}; diff --git a/components/FileView/FileView.vue b/components/FileView/FileView.vue deleted file mode 100644 index 3d025634..00000000 --- a/components/FileView/FileView.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - diff --git a/components/HttpDumpPreview/HttpDumpPreview.stories.ts b/components/HttpDumpPreview/HttpDumpPreview.stories.ts deleted file mode 100644 index 88d6c1a9..00000000 --- a/components/HttpDumpPreview/HttpDumpPreview.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeHttpDumpEvent } from "~/utils/normalize-event"; -import httpDumpEventMock from '~/mocks/http-dump.json' -import HttpDumpPreview from '~/components/HttpDumpPreview/HttpDumpPreview.vue'; - -export default { - title: "HttpDump/Components/HttpDumpPreview", - component: HttpDumpPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { HttpDumpPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Event = Template.bind({}); - -Event.args = { - event: normalizeHttpDumpEvent(httpDumpEventMock), -}; diff --git a/components/HttpDumpPreview/HttpDumpPreview.vue b/components/HttpDumpPreview/HttpDumpPreview.vue deleted file mode 100644 index ec6ae2d1..00000000 --- a/components/HttpDumpPreview/HttpDumpPreview.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - diff --git a/components/InspectorPreview/InspectorPreview.stories.ts b/components/InspectorPreview/InspectorPreview.stories.ts deleted file mode 100644 index 09060cde..00000000 --- a/components/InspectorPreview/InspectorPreview.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeInspectorEvent } from "~/utils/normalize-event"; -import inspectorEventMock from '~/mocks/inspector.json' -import InspectorPreview from '~/components/InspectorPreview/InspectorPreview.vue'; - -export default { - title: "Inspector/Components/InspectorPreview", - component: InspectorPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { InspectorPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Event = Template.bind({}); - -Event.args = { - event: normalizeInspectorEvent(inspectorEventMock), -}; diff --git a/components/InspectorPreview/InspectorPreview.vue b/components/InspectorPreview/InspectorPreview.vue deleted file mode 100644 index 92260046..00000000 --- a/components/InspectorPreview/InspectorPreview.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/components/MonologPreview/MonologPreview.stories.ts b/components/MonologPreview/MonologPreview.stories.ts deleted file mode 100644 index f8e8b400..00000000 --- a/components/MonologPreview/MonologPreview.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeMonologEvent } from "~/utils/normalize-event"; -import monologEventMock from '~/mocks/monolog.json' -import MonologPreview from '~/components/MonologPreview/MonologPreview.vue'; - -export default { - title: "Monolog/Components/Preview", - component: MonologPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { MonologPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Event = Template.bind({}); - -Event.args = { - event: normalizeMonologEvent(monologEventMock), -}; diff --git a/components/MonologPreview/MonologPreview.vue b/components/MonologPreview/MonologPreview.vue deleted file mode 100644 index 311b7f4c..00000000 --- a/components/MonologPreview/MonologPreview.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - - - diff --git a/components/PagePlaceholder/PagePlaceholder.vue b/components/PagePlaceholder/PagePlaceholder.vue deleted file mode 100644 index e085c503..00000000 --- a/components/PagePlaceholder/PagePlaceholder.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - - - diff --git a/components/PreviewCard/PreviewCard.vue b/components/PreviewCard/PreviewCard.vue deleted file mode 100644 index f9c51d60..00000000 --- a/components/PreviewCard/PreviewCard.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - - - diff --git a/components/PreviewEventMapper/PreviewEventMapper.vue b/components/PreviewEventMapper/PreviewEventMapper.vue deleted file mode 100644 index 2e918538..00000000 --- a/components/PreviewEventMapper/PreviewEventMapper.vue +++ /dev/null @@ -1,78 +0,0 @@ - diff --git a/components/PreviewFallback/PreviewFallback.stories.ts b/components/PreviewFallback/PreviewFallback.stories.ts deleted file mode 100644 index 86e05d77..00000000 --- a/components/PreviewFallback/PreviewFallback.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeFallbackEvent } from "~/utils/normalize-event"; -import monologEventMock from '~/mocks/monolog.json' -import PreviewFallback from '~/components/PreviewFallback/PreviewFallback.vue'; - -export default { - title: "Preview/PreviewFallback", - component: PreviewFallback -} as Meta; - -const Template: Story = (args) => ({ - components: { PreviewFallback }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Default = Template.bind({}); - -Default.args = { - event: normalizeFallbackEvent({ ...monologEventMock, type: 'unknown' }), -}; diff --git a/components/PreviewFallback/PreviewFallback.vue b/components/PreviewFallback/PreviewFallback.vue deleted file mode 100644 index c04865e8..00000000 --- a/components/PreviewFallback/PreviewFallback.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/components/ProfilePageFlamegraph/ProfilePageFlamegraph.stories.ts b/components/ProfilePageFlamegraph/ProfilePageFlamegraph.stories.ts deleted file mode 100644 index 3dcdb948..00000000 --- a/components/ProfilePageFlamegraph/ProfilePageFlamegraph.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {Meta, Story} from "@storybook/vue3"; -import {normalizeProfilerEvent} from "~/utils/normalize-event"; -import profilerEventMock from '~/mocks/profiler.json' -import { Profiler } from "~/config/types"; -import ProfilePageFlamegraph from '~/components/ProfilePageFlamegraph/ProfilePageFlamegraph.vue'; - -export default { - title: "Profiler/Page/ProfilePageFlamegraph", - component: ProfilePageFlamegraph -} as Meta; - -const Template: Story = (args) => ({ - components: {ProfilePageFlamegraph}, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Default = Template.bind({}); - -Default.args = { - edges: (normalizeProfilerEvent(profilerEventMock).payload as Profiler).edges, -}; diff --git a/components/ProfilePageFlamegraph/ProfilePageFlamegraph.vue b/components/ProfilePageFlamegraph/ProfilePageFlamegraph.vue deleted file mode 100644 index 06caf04b..00000000 --- a/components/ProfilePageFlamegraph/ProfilePageFlamegraph.vue +++ /dev/null @@ -1,99 +0,0 @@ - - - - - diff --git a/components/ProfilerPage/ProfilerPage.vue b/components/ProfilerPage/ProfilerPage.vue deleted file mode 100644 index 2f8f4e94..00000000 --- a/components/ProfilerPage/ProfilerPage.vue +++ /dev/null @@ -1,234 +0,0 @@ - - - - - diff --git a/components/ProfilerPageCallGraph/ProfilerPageCallGraph.stories.ts b/components/ProfilerPageCallGraph/ProfilerPageCallGraph.stories.ts deleted file mode 100644 index 7694bf49..00000000 --- a/components/ProfilerPageCallGraph/ProfilerPageCallGraph.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import ProfilerPageCallGraph from '~/components/ProfilerPageCallGraph/ProfilerPageCallGraph.vue'; -import profilerEventMock from '~/mocks/profiler.json' - -export default { - title: "Profiler/Page/ProfilerPageCallGraph", - component: ProfilerPageCallGraph -} as Meta; - -const Template: Story = (args) => ({ - components: { ProfilerPageCallGraph }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const CallGraph = Template.bind({}); - -CallGraph.args = { - event: normalizeProfilerEvent(profilerEventMock).payload, -}; diff --git a/components/ProfilerPageCallGraph/ProfilerPageCallGraph.vue b/components/ProfilerPageCallGraph/ProfilerPageCallGraph.vue deleted file mode 100644 index 3fef5fa7..00000000 --- a/components/ProfilerPageCallGraph/ProfilerPageCallGraph.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - - - diff --git a/components/ProfilerPageCallStack/ProfilerPageCallStack.stories.ts b/components/ProfilerPageCallStack/ProfilerPageCallStack.stories.ts deleted file mode 100644 index 5a5b2695..00000000 --- a/components/ProfilerPageCallStack/ProfilerPageCallStack.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import ProfilerPageCallStack from '~/components/ProfilerPageCallStack/ProfilerPageCallStack.vue'; -import profilerEventMock from '~/mocks/profiler.json' - -export default { - title: "Profiler/Page/ProfilerPageCallStack", - component: ProfilerPageCallStack -} as Meta; - -const Template: Story = (args) => ({ - components: { ProfilerPageCallStack }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const List = Template.bind({}); - -List.args = { - event: normalizeProfilerEvent(profilerEventMock).payload, -}; diff --git a/components/ProfilerPageCallStack/ProfilerPageCallStack.vue b/components/ProfilerPageCallStack/ProfilerPageCallStack.vue deleted file mode 100644 index 72bdbca3..00000000 --- a/components/ProfilerPageCallStack/ProfilerPageCallStack.vue +++ /dev/null @@ -1,126 +0,0 @@ - - - - - diff --git a/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.stories.ts b/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.stories.ts deleted file mode 100644 index 4a9261c4..00000000 --- a/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import ProfilerPageCallStackRow from '~/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.vue'; -import profilerEventMock from '~/mocks/profiler.json' - -export default { - title: "Profiler/Page/ProfilerPageCallStackRow", - component: ProfilerPageCallStackRow -} as Meta; - -const Template: Story = (args) => ({ - components: { ProfilerPageCallStackRow }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Row = Template.bind({}); - -Row.args = { - edge: normalizeProfilerEvent(profilerEventMock).payload.edges.e5, -}; diff --git a/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.vue b/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.vue deleted file mode 100644 index 421d68c5..00000000 --- a/components/ProfilerPageCallStackRow/ProfilerPageCallStackRow.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - - - diff --git a/components/ProfilerPreview/ProfilerPreview.stories.ts b/components/ProfilerPreview/ProfilerPreview.stories.ts deleted file mode 100644 index bcfd3288..00000000 --- a/components/ProfilerPreview/ProfilerPreview.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import profilerEventMock from '~/mocks/profiler.json' -import ProfilerPreview from '~/components/ProfilerPreview/ProfilerPreview.vue'; - -export default { - title: "Profiler/Components/ProfilerPreview", - component: ProfilerPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { ProfilerPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Event = Template.bind({}); - -Event.args = { - event: normalizeProfilerEvent(profilerEventMock), -}; diff --git a/components/ProfilerPreview/ProfilerPreview.vue b/components/ProfilerPreview/ProfilerPreview.vue deleted file mode 100644 index fa085a7a..00000000 --- a/components/ProfilerPreview/ProfilerPreview.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayDumpLaravelPreview.stories.ts b/components/RayDumpPreview/RayDumpLaravelPreview.stories.ts deleted file mode 100644 index 6c6d6754..00000000 --- a/components/RayDumpPreview/RayDumpLaravelPreview.stories.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import RayDumpPreview from '~/components/RayDumpPreview/RayDumpPreview.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import rayQueryEventMock from '~/mocks/ray-laravel-query.json' -import rayQuery2EventMock from '~/mocks/ray-laravel-query-no-bindings.json' -import rayEloquentEventMock from '~/mocks/ray-laravel-eloquent.json' -import rayViewsEventMock from '~/mocks/ray-laravel-views.json' -import rayEventsEventMock from '~/mocks/ray-laravel-events.json' -import rayJobsEventMock from '~/mocks/ray-laravel-jobs.json' - -export default { - title: "RayDump/RayDumpPreview/Laravel", - component: RayDumpPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { RayDumpPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Query = Template.bind({}); -Query.args = {event: normalizeRayDumpEvent(rayQueryEventMock),}; - -export const Query2 = Template.bind({}); -Query2.args = {event: normalizeRayDumpEvent(rayQuery2EventMock),}; - -export const Eloquent = Template.bind({}); -Eloquent.args = {event: normalizeRayDumpEvent(rayEloquentEventMock),}; - -export const Views = Template.bind({}); -Views.args = {event: normalizeRayDumpEvent(rayViewsEventMock),}; - -export const Events = Template.bind({}); -Events.args = {event: normalizeRayDumpEvent(rayEventsEventMock),}; - -export const Jobs = Template.bind({}); -Jobs.args = {event: normalizeRayDumpEvent(rayJobsEventMock),}; diff --git a/components/RayDumpPreview/RayDumpPreview.stories.ts b/components/RayDumpPreview/RayDumpPreview.stories.ts deleted file mode 100644 index c6510db2..00000000 --- a/components/RayDumpPreview/RayDumpPreview.stories.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import RayDumpPreview from '~/components/RayDumpPreview/RayDumpPreview.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import rayIntEventMock from '~/mocks/ray-int.json' -import rayCallerEventMock from '~/mocks/ray-caller.json' -import rayCarbonEventMock from '~/mocks/ray-carbon.json' -import rayColorEventMock from '~/mocks/ray-color.json' -import rayCounterEventMock from '~/mocks/ray-counter.json' -import rayDumpEventMock from '~/mocks/ray-dump.json' -import rayExceptionEventMock from '~/mocks/ray-exception.json' -import rayHideEventMock from '~/mocks/ray-hide.json' -import rayImageEventMock from '~/mocks/ray-image.json' -import rayJsonEventMock from '~/mocks/ray-json.json' -import rayLabelEventMock from '~/mocks/ray-label.json' -import rayMeasureEventMock from '~/mocks/ray-measure.json' -import rayNotifyEventMock from '~/mocks/ray-notify.json' -import raySizeEventMock from '~/mocks/ray-size.json' -import rayTableEventMock from '~/mocks/ray-table.json' -import rayTextEventMock from '~/mocks/ray-text.json' -import rayTraceEventMock from '~/mocks/ray-trace.json' -import rayLockEventMock from '~/mocks/ray-lock.json' -import rayIssue44EventMock from '~/mocks/ray-github-issue-44.json' - -export default { - title: "RayDump/RayDumpPreview/Common", - component: RayDumpPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { RayDumpPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Text = Template.bind({}); - -Text.args = {event: normalizeRayDumpEvent(rayTextEventMock),}; - -export const Trace = Template.bind({}); -Trace.args = {event: normalizeRayDumpEvent(rayTraceEventMock),}; - -export const Table = Template.bind({}); -Table.args = {event: normalizeRayDumpEvent(rayTableEventMock),}; - -export const Size = Template.bind({}); -Size.args = {event: normalizeRayDumpEvent(raySizeEventMock),}; - -export const Notify = Template.bind({}); -Notify.args = {event: normalizeRayDumpEvent(rayNotifyEventMock),}; - -export const Measure = Template.bind({}); -Measure.args = {event: normalizeRayDumpEvent(rayMeasureEventMock),}; - -export const Label = Template.bind({}); -Label.args = {event: normalizeRayDumpEvent(rayLabelEventMock),}; - -export const Json = Template.bind({}); -Json.args = {event: normalizeRayDumpEvent(rayJsonEventMock),}; - -export const Image = Template.bind({}); -Image.args = {event: normalizeRayDumpEvent(rayImageEventMock),}; - -export const Hide = Template.bind({}); -Hide.args = {event: normalizeRayDumpEvent(rayHideEventMock),}; - -export const Exception = Template.bind({}); -Exception.args = {event: normalizeRayDumpEvent(rayExceptionEventMock),}; - -export const Dump = Template.bind({}); -Dump.args = {event: normalizeRayDumpEvent(rayDumpEventMock),}; - -export const Counter = Template.bind({}); -Counter.args = {event: normalizeRayDumpEvent(rayCounterEventMock),}; - -export const Color = Template.bind({}); -Color.args = {event: normalizeRayDumpEvent(rayColorEventMock),}; - -export const Carbon = Template.bind({}); -Carbon.args = {event: normalizeRayDumpEvent(rayCarbonEventMock),}; - -export const Int = Template.bind({}); -Int.args = {event: normalizeRayDumpEvent(rayIntEventMock),}; - -export const Caller = Template.bind({}); -Caller.args = {event: normalizeRayDumpEvent(rayCallerEventMock),}; - -export const Lock = Template.bind({}); -Lock.args = {event: normalizeRayDumpEvent(rayLockEventMock),}; - -export const Issue44 = Template.bind({}); -Issue44.args = {event: normalizeRayDumpEvent(rayIssue44EventMock),}; diff --git a/components/RayDumpPreview/RayDumpPreview.vue b/components/RayDumpPreview/RayDumpPreview.vue deleted file mode 100644 index 0adf2dc4..00000000 --- a/components/RayDumpPreview/RayDumpPreview.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - diff --git a/components/RayDumpPreview/RayTypesPreview/CallerPayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/CallerPayload.stories.ts deleted file mode 100644 index edfb5c4f..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CallerPayload.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import CallerPayload from '~/components/RayDumpPreview/RayTypesPreview/CallerPayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import rayCallerEventMock from '~/mocks/ray-caller.json' - -export default { - title: "RayDump/Types/Caller", - component: CallerPayload -} as Meta; - -const Template: Story = (args) => ({ - components: { CallerPayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Caller = Template.bind({}); -Caller.args = {payload: normalizeRayDumpEvent(rayCallerEventMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/CallerPayload.vue b/components/RayDumpPreview/RayTypesPreview/CallerPayload.vue deleted file mode 100644 index 6bb963dd..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CallerPayload.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/CarbonPayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/CarbonPayload.stories.ts deleted file mode 100644 index 2b3dfe9e..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CarbonPayload.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import CarbonPayload from '~/components/RayDumpPreview/RayTypesPreview/CarbonPayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-carbon.json' - -export default { - title: "RayDump/Types/Carbon", - component: CarbonPayload -} as Meta; - -const Template: Story = (args) => ({ - components: { CarbonPayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Carbon = Template.bind({}); -Carbon.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/CarbonPayload.vue b/components/RayDumpPreview/RayTypesPreview/CarbonPayload.vue deleted file mode 100644 index 48ade7b5..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CarbonPayload.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/CustomPayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/CustomPayload.stories.ts deleted file mode 100644 index 99778c66..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CustomPayload.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import CustomPayload from '~/components/RayDumpPreview/RayTypesPreview/CustomPayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-text.json' - -export default { - title: "RayDump/Types/Custom", - component: CustomPayload -} as Meta; - -const Template: Story = (args) => ({ - components: { CustomPayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Custom = Template.bind({}); -Custom.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/CustomPayload.vue b/components/RayDumpPreview/RayTypesPreview/CustomPayload.vue deleted file mode 100644 index 8b1a2341..00000000 --- a/components/RayDumpPreview/RayTypesPreview/CustomPayload.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/EloquentPayload.vue b/components/RayDumpPreview/RayTypesPreview/EloquentPayload.vue deleted file mode 100644 index dc1a957b..00000000 --- a/components/RayDumpPreview/RayTypesPreview/EloquentPayload.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/EventPayload.vue b/components/RayDumpPreview/RayTypesPreview/EventPayload.vue deleted file mode 100644 index 7c4da38a..00000000 --- a/components/RayDumpPreview/RayTypesPreview/EventPayload.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.stories.ts deleted file mode 100644 index e9e2be9f..00000000 --- a/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import ExceptionPayload from '~/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-exception.json' - -export default { - title: "RayDump/Types/Exception", - component: ExceptionPayload -} as Meta; - -const Template: Story = (args) => ({ - components: { ExceptionPayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Exception = Template.bind({}); -Exception.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.vue b/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.vue deleted file mode 100644 index 3dccd5c3..00000000 --- a/components/RayDumpPreview/RayTypesPreview/ExceptionPayload.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/JobPayload.vue b/components/RayDumpPreview/RayTypesPreview/JobPayload.vue deleted file mode 100644 index 8ed217c4..00000000 --- a/components/RayDumpPreview/RayTypesPreview/JobPayload.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/LockPayload.vue b/components/RayDumpPreview/RayTypesPreview/LockPayload.vue deleted file mode 100644 index d1aa23cf..00000000 --- a/components/RayDumpPreview/RayTypesPreview/LockPayload.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/LogPayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/LogPayload.stories.ts deleted file mode 100644 index 1506f013..00000000 --- a/components/RayDumpPreview/RayTypesPreview/LogPayload.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import LogPayload from '~/components/RayDumpPreview/RayTypesPreview/LogPayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-color.json' - -export default { - title: "RayDump/Types/Log", - component: LogPayload -} as Meta; - -const Template: Story = (args) => ({ - components: { LogPayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Log = Template.bind({}); -Log.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/LogPayload.vue b/components/RayDumpPreview/RayTypesPreview/LogPayload.vue deleted file mode 100644 index a94d7404..00000000 --- a/components/RayDumpPreview/RayTypesPreview/LogPayload.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/MailablePayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/MailablePayload.stories.ts deleted file mode 100644 index 08352965..00000000 --- a/components/RayDumpPreview/RayTypesPreview/MailablePayload.stories.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-laravel-mailable.json'; -import MailablePayload from "~/components/RayDumpPreview/RayTypesPreview/MailablePayload.vue"; - -export default { - title: "RayDump/Types/Mailable", - component: MailablePayload -} as Meta; - -const Template: Story = (args) => ({ - components: { MailablePayload}, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Mailable = Template.bind({}); -Mailable.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; - diff --git a/components/RayDumpPreview/RayTypesPreview/MailablePayload.vue b/components/RayDumpPreview/RayTypesPreview/MailablePayload.vue deleted file mode 100644 index 2293ff7b..00000000 --- a/components/RayDumpPreview/RayTypesPreview/MailablePayload.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/MeasurePayload.stories.ts b/components/RayDumpPreview/RayTypesPreview/MeasurePayload.stories.ts deleted file mode 100644 index 5a2d6768..00000000 --- a/components/RayDumpPreview/RayTypesPreview/MeasurePayload.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import MeasurePayload from '~/components/RayDumpPreview/RayTypesPreview/MeasurePayload.vue'; -import { normalizeRayDumpEvent } from "~/utils/normalize-event"; -import eventMock from '~/mocks/ray-measure.json'; -import eventStartMock from '~/mocks/ray-measure-start.json'; - -export default { - title: "RayDump/Types/Measure", - component: MeasurePayload -} as Meta; - -const Template: Story = (args) => ({ - components: { MeasurePayload }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Default = Template.bind({}); -Default.args = {payload: normalizeRayDumpEvent(eventMock).payload.payload.payloads[0]}; - -export const Start = Template.bind({}); -Start.args = {payload: normalizeRayDumpEvent(eventStartMock).payload.payload.payloads[0]}; diff --git a/components/RayDumpPreview/RayTypesPreview/MeasurePayload.vue b/components/RayDumpPreview/RayTypesPreview/MeasurePayload.vue deleted file mode 100644 index ee621eb7..00000000 --- a/components/RayDumpPreview/RayTypesPreview/MeasurePayload.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/NotifyPayload.vue b/components/RayDumpPreview/RayTypesPreview/NotifyPayload.vue deleted file mode 100644 index bd3816de..00000000 --- a/components/RayDumpPreview/RayTypesPreview/NotifyPayload.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/QueryPayload.vue b/components/RayDumpPreview/RayTypesPreview/QueryPayload.vue deleted file mode 100644 index 8463e5e5..00000000 --- a/components/RayDumpPreview/RayTypesPreview/QueryPayload.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/TablePayload.vue b/components/RayDumpPreview/RayTypesPreview/TablePayload.vue deleted file mode 100644 index add34732..00000000 --- a/components/RayDumpPreview/RayTypesPreview/TablePayload.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/TracePayload.vue b/components/RayDumpPreview/RayTypesPreview/TracePayload.vue deleted file mode 100644 index 676ee0eb..00000000 --- a/components/RayDumpPreview/RayTypesPreview/TracePayload.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - - - diff --git a/components/RayDumpPreview/RayTypesPreview/ViewsPayload.vue b/components/RayDumpPreview/RayTypesPreview/ViewsPayload.vue deleted file mode 100644 index 7f5fc0be..00000000 --- a/components/RayDumpPreview/RayTypesPreview/ViewsPayload.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/components/RayDumpTypeMapper/RayDumpTypeMapper.vue b/components/RayDumpTypeMapper/RayDumpTypeMapper.vue deleted file mode 100644 index 5e8e7243..00000000 --- a/components/RayDumpTypeMapper/RayDumpTypeMapper.vue +++ /dev/null @@ -1,80 +0,0 @@ - diff --git a/components/RenderGraph/RenderGraph.vue b/components/RenderGraph/RenderGraph.vue deleted file mode 100644 index 8da7eb02..00000000 --- a/components/RenderGraph/RenderGraph.vue +++ /dev/null @@ -1,173 +0,0 @@ - - - - - diff --git a/components/SentryException/SentryException.stories.ts b/components/SentryException/SentryException.stories.ts deleted file mode 100644 index 940c40ac..00000000 --- a/components/SentryException/SentryException.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryEventMock from '~/mocks/sentry-common.json' -import { Sentry } from "~/config/types"; -import SentryException from '~/components/SentryException/SentryException.vue'; - -export default { - title: "Sentry/Components/SentryException", - component: SentryException -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryException }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Exception = Template.bind({}); - -Exception.args = { - exception: (normalizeSentryEvent(sentryEventMock)?.payload as Sentry)?.exception?.values[0], -}; diff --git a/components/SentryExceptionFrame/SentryExceptionFrame.stories.ts b/components/SentryExceptionFrame/SentryExceptionFrame.stories.ts deleted file mode 100644 index e84403d4..00000000 --- a/components/SentryExceptionFrame/SentryExceptionFrame.stories.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentrySpiralEventMock from '~/mocks/sentry-spiral.json' -import { Sentry } from "~/config/types"; -import SentryExceptionFrame from '~/components/SentryExceptionFrame/SentryExceptionFrame.vue'; - -export default { - title: "Sentry/Components/SentryExceptionFrame", - component: SentryExceptionFrame -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryExceptionFrame }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Frame = Template.bind({}); - -Frame.args = { - isOpen: true, - frame: (normalizeSentryEvent(sentrySpiralEventMock)?.payload as Sentry)?.exception?.values[0]?.stacktrace?.frames[1], -}; diff --git a/components/SentryPage/SentryPage.vue b/components/SentryPage/SentryPage.vue deleted file mode 100644 index a75b43df..00000000 --- a/components/SentryPage/SentryPage.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/components/SentryPageApp/SentryPageApp.stories.ts b/components/SentryPageApp/SentryPageApp.stories.ts deleted file mode 100644 index 2ea284e9..00000000 --- a/components/SentryPageApp/SentryPageApp.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryEventMock from '~/mocks/sentry-common.json' -import SentryPageApp from '~/components/SentryPageApp/SentryPageApp.vue'; - -export default { - title: "Sentry/Page/SentryPageApp", - component: SentryPageApp -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPageApp }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const App = Template.bind({}); - -App.args = { - event: normalizeSentryEvent(sentryEventMock).payload, -}; diff --git a/components/SentryPageApp/SentryPageApp.vue b/components/SentryPageApp/SentryPageApp.vue deleted file mode 100644 index 5efc0a73..00000000 --- a/components/SentryPageApp/SentryPageApp.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.stories.ts b/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.stories.ts deleted file mode 100644 index 20ce1716..00000000 --- a/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.stories.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryLaravelEventMock from '~/mocks/sentry-laravel.json' -import sentrySpiralEventMock from '~/mocks/sentry-spiral.json' -import SentryPageBreadcrumbs from '~/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.vue'; - -export default { - title: "Sentry/Page/SentryPageBreadcrumbs", - component: SentryPageBreadcrumbs -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPageBreadcrumbs }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Laravel = Template.bind({}); - -Laravel.args = { - event: normalizeSentryEvent(sentryLaravelEventMock).payload, -}; - -export const Spiral = Template.bind({}); - -Spiral.args = { - event: normalizeSentryEvent(sentrySpiralEventMock).payload, -}; diff --git a/components/SentryPageDevice/SentryPageDevice.stories.ts b/components/SentryPageDevice/SentryPageDevice.stories.ts deleted file mode 100644 index af833f72..00000000 --- a/components/SentryPageDevice/SentryPageDevice.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryEventMock from '~/mocks/sentry-common.json' -import SentryPageDevice from '~/components/SentryPageDevice/SentryPageDevice.vue'; - -export default { - title: "Sentry/Page/SentryPageDevice", - component: SentryPageDevice -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPageDevice }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Device = Template.bind({}); - -Device.args = { - event: normalizeSentryEvent(sentryEventMock).payload, -}; diff --git a/components/SentryPageDevice/SentryPageDevice.vue b/components/SentryPageDevice/SentryPageDevice.vue deleted file mode 100644 index 338e2249..00000000 --- a/components/SentryPageDevice/SentryPageDevice.vue +++ /dev/null @@ -1,170 +0,0 @@ - - - - - diff --git a/components/SentryPageRequest/SentryPageRequest.stories.ts b/components/SentryPageRequest/SentryPageRequest.stories.ts deleted file mode 100644 index efc9ca84..00000000 --- a/components/SentryPageRequest/SentryPageRequest.stories.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryLaravelEventMock from '~/mocks/sentry-laravel.json' -import sentrySpiralEventMock from '~/mocks/sentry-spiral.json' -import SentryPageRequest from '~/components/SentryPageRequest/SentryPageRequest.vue'; - -export default { - title: "Sentry/Page/SentryPageRequest", - component: SentryPageRequest -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPageRequest }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Laravel = Template.bind({}); - -Laravel.args = { - event: normalizeSentryEvent(sentryLaravelEventMock).payload, -}; - -export const Spiral = Template.bind({}); - -Spiral.args = { - event: normalizeSentryEvent(sentrySpiralEventMock).payload, -}; diff --git a/components/SentryPageRequest/SentryPageRequest.vue b/components/SentryPageRequest/SentryPageRequest.vue deleted file mode 100644 index b278bde8..00000000 --- a/components/SentryPageRequest/SentryPageRequest.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - - diff --git a/components/SentryPageTags/SentryPageTags.stories.ts b/components/SentryPageTags/SentryPageTags.stories.ts deleted file mode 100644 index f99bcb5f..00000000 --- a/components/SentryPageTags/SentryPageTags.stories.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentryLaravelEventMock from '~/mocks/sentry-laravel.json' -import sentrySpiralEventMock from '~/mocks/sentry-spiral.json' -import SentryPageTags from '~/components/SentryPageTags/SentryPageTags.vue'; - -export default { - title: "Sentry/Page/SentryPageTags", - component: SentryPageTags -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPageTags }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Laravel = Template.bind({}); - -Laravel.args = { - event: normalizeSentryEvent(sentryLaravelEventMock).payload, -}; - -export const Spiral = Template.bind({}); - -Spiral.args = { - event: normalizeSentryEvent(sentrySpiralEventMock).payload, -}; diff --git a/components/SentryPreview/SentryPreview.stories.ts b/components/SentryPreview/SentryPreview.stories.ts deleted file mode 100644 index c2d33493..00000000 --- a/components/SentryPreview/SentryPreview.stories.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSentryEvent } from "~/utils/normalize-event"; -import sentrySpiralEventMock from '~/mocks/sentry-spiral.json' -import sentryLaravelEventMock from '~/mocks/sentry-laravel.json' -import sentryEventMock from '~/mocks/sentry-event.json' -import sentryJsEventMock from '~/mocks/sentry-js-event.json' -import SentryPreview from '~/components/SentryPreview/SentryPreview.vue'; - -export default { - title: "Sentry/Components/SentryPreview", - component: SentryPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { SentryPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Spiral = Template.bind({}); - -Spiral.args = { - event: normalizeSentryEvent(sentrySpiralEventMock), -}; - -export const Laravel = Template.bind({}); - -Laravel.args = { - event: normalizeSentryEvent(sentryLaravelEventMock), -}; - -export const Event = Template.bind({}); - -Event.args = { - event: normalizeSentryEvent(sentryEventMock), -}; - -export const JSEvent = Template.bind({}); - -JSEvent.args = { - event: normalizeSentryEvent(sentryJsEventMock), -}; - diff --git a/components/SentryPreview/SentryPreview.vue b/components/SentryPreview/SentryPreview.vue deleted file mode 100644 index f7025741..00000000 --- a/components/SentryPreview/SentryPreview.vue +++ /dev/null @@ -1,104 +0,0 @@ - - - - - diff --git a/components/SmtpAttachment/SmtpAttachment.vue b/components/SmtpAttachment/SmtpAttachment.vue deleted file mode 100644 index a2769391..00000000 --- a/components/SmtpAttachment/SmtpAttachment.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - - - diff --git a/components/SmtpPage/SmtpPage.stories.ts b/components/SmtpPage/SmtpPage.stories.ts deleted file mode 100644 index 3be23f91..00000000 --- a/components/SmtpPage/SmtpPage.stories.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSMTPEvent } from "~/utils/normalize-event"; -import smtpEventWelcomeMock from '~/mocks/smtp-welcome.json' -import smtpEventOrderMock from '~/mocks/smtp-order.json' -import smtpEventTextMock from '~/mocks/smtp-text.json' -import SmtpPage from "~/components/SmtpPage/SmtpPage.vue"; - -export default { - title: "Smtp/Page/SmtpPage", - component: SmtpPage -} as Meta; - -const Template: Story = (args) => ({ - components: { SmtpPage }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -const normalizeEventWelcome = normalizeSMTPEvent(smtpEventWelcomeMock) -const normalizeEventOrder = normalizeSMTPEvent(smtpEventOrderMock) -const normalizeEventText = normalizeSMTPEvent(smtpEventTextMock) - -export const Default = Template.bind({}); -Default.args = { - event: normalizeEventWelcome, - htmlSource: normalizeEventWelcome.payload.html -}; - -export const Order = Template.bind({}); -Order.args = { - event: normalizeEventOrder, - htmlSource: normalizeEventOrder.payload.html -}; - -export const Text = Template.bind({}); -Text.args = { - event: normalizeEventText, - htmlSource: normalizeEventText.payload.html -}; diff --git a/components/SmtpPageAddresses/SmtpPageAddresses.stories.ts b/components/SmtpPageAddresses/SmtpPageAddresses.stories.ts deleted file mode 100644 index e6200550..00000000 --- a/components/SmtpPageAddresses/SmtpPageAddresses.stories.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Meta, Story} from "@storybook/vue3"; -import SmtpPageAddresses from '~/components/SmtpPageAddresses/SmtpPageAddresses.vue'; - -export default { - title: "Smtp/Page/SmtpPageAddresses", - component: SmtpPageAddresses -} as Meta; - -const Template: Story = (args) => ({ - components: {SmtpPageAddresses}, - setup() { - return { - args, - }; - }, - template: ` - `, -}); - -export const EmailAddresses = Template.bind({}); - -EmailAddresses.args = { - addresses: [ - { - name: 'John Doe', - email: 'john-doe@example.com', - }, - { - name: 'Jane Smith', - email: 'JaneSmith@example.com', - }, - { - email: 'saraConor@example.com', - } - ], -}; diff --git a/components/SmtpPreview/SmtpPreview.stories.ts b/components/SmtpPreview/SmtpPreview.stories.ts deleted file mode 100644 index 3a198fc1..00000000 --- a/components/SmtpPreview/SmtpPreview.stories.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeSMTPEvent } from "~/utils/normalize-event"; -import smtpOrderShippedEventMock from '~/mocks/smtp-order.json'; -import smtpWelcomeEventMock from '~/mocks/smtp-welcome.json'; -import SmtpPreview from '~/components/SmtpPreview/SmtpPreview.vue'; - -export default { - title: "SMTP/Components/SmtpPreview", - component: SmtpPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { SmtpPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const OrderShipped = Template.bind({}); - -OrderShipped.args = { - event: normalizeSMTPEvent(smtpOrderShippedEventMock), -}; - -export const Welcome = Template.bind({}); - -Welcome.args = { - event: normalizeSMTPEvent(smtpWelcomeEventMock), -}; diff --git a/components/SortWrap/SortWrap.vue b/components/SortWrap/SortWrap.vue deleted file mode 100644 index d1b5c3c8..00000000 --- a/components/SortWrap/SortWrap.vue +++ /dev/null @@ -1,81 +0,0 @@ - - - - - diff --git a/components/StatBoard/StatBoard.vue b/components/StatBoard/StatBoard.vue deleted file mode 100644 index eda4f8b6..00000000 --- a/components/StatBoard/StatBoard.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - - - diff --git a/components/ValueDump/ValueDump.vue b/components/ValueDump/ValueDump.vue deleted file mode 100644 index 126c4693..00000000 --- a/components/ValueDump/ValueDump.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/components/VarDumpPreview/VarDumpPreview.stories.ts b/components/VarDumpPreview/VarDumpPreview.stories.ts deleted file mode 100644 index e947c9db..00000000 --- a/components/VarDumpPreview/VarDumpPreview.stories.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Meta, Story } from "@storybook/vue3"; -import { normalizeVarDumpEvent } from "~/utils/normalize-event"; - -import varDumpObjectEventMock from '~/mocks/var-dump-object.json' -import varDumpNumberEventMock from '~/mocks/var-dump-number.json' -import varDumpStringEventMock from '~/mocks/var-dump-string.json' -import varDumpStringEmptyEventMock from '~/mocks/var-dump-string-empty.json' -import varDumpArrayEventMock from '~/mocks/var-dump-array.json' -import varDumpBoolTrueEventMock from '~/mocks/var-dump-boolean-true.json' -import varDumpBoolFalseEventMock from '~/mocks/var-dump-boolean-false.json' -import VarDumpPreview from '~/components/VarDumpPreview/VarDumpPreview.vue'; - -export default { - title: "VarDump/Components/Preview", - component: VarDumpPreview -} as Meta; - -const Template: Story = (args) => ({ - components: { VarDumpPreview }, - setup() { - return { - args, - }; - }, - template: ``, -}); - -export const Object = Template.bind({}); - -Object.args = { - event: normalizeVarDumpEvent(varDumpObjectEventMock), -}; - -export const Number = Template.bind({}); - -Number.args = { - event: normalizeVarDumpEvent(varDumpNumberEventMock), -}; - -export const String = Template.bind({}); - -String.args = { - event: normalizeVarDumpEvent(varDumpStringEventMock), -}; - -export const StringEmpty = Template.bind({}); - -StringEmpty.args = { - event: normalizeVarDumpEvent(varDumpStringEmptyEventMock), -}; - -export const BooleanTrue = Template.bind({}); - -BooleanTrue.args = { - event: normalizeVarDumpEvent(varDumpBoolTrueEventMock), -}; - -export const BooleanFalse = Template.bind({}); -BooleanFalse.args = { - event: normalizeVarDumpEvent(varDumpBoolFalseEventMock), -}; - - -export const Array = Template.bind({}); - -Array.args = { - event: normalizeVarDumpEvent(varDumpArrayEventMock), -}; diff --git a/components/VarDumpPreview/VarDumpPreview.vue b/components/VarDumpPreview/VarDumpPreview.vue deleted file mode 100644 index 0e5f3082..00000000 --- a/components/VarDumpPreview/VarDumpPreview.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - - - diff --git a/config/constants.ts b/config/constants.ts deleted file mode 100644 index 83dddb65..00000000 --- a/config/constants.ts +++ /dev/null @@ -1,61 +0,0 @@ -export const EVENT_TYPES = { - VAR_DUMP: "var-dump", - SMTP: "smtp", - SENTRY: "sentry", - PROFILER: "profiler", - MONOLOG: "monolog", - INSPECTOR: "inspector", - HTTP_DUMP: "http-dump", - RAY_DUMP: "ray", -}; - -export const ALL_EVENTS = 'ALL EVENTS' - -export const RAY_EVENT_TYPES = { - LOG: "log", - // SIZE: "size", - CUSTOM: "custom", - // LABEL: "label", - CALLER: "caller", - CARBON: "carbon", - // COLOR: "color", - EXCEPTION: "exception", - // HIDE: "hide", - MEASURE: "measure", - NOTIFY: "notify", - MAILABLE: "mailable", - TABLE: "table", - TRACE: "trace", - QUERY: "executed_query", - ELOQUENT: "eloquent_model", - VIEW: "view", - EVENT: "event", - JOB: "job_event", - LOCK: "create_lock", -} - -// TODO: colors should depends on level for some tools -export const EVENT_STATUS_COLOR_MAP = { - CRITICAL: "red", - ERROR: "red", - ALERT: "red", - EMERGENCY: "red", - WARNING: "orange", - INFO: "blue", - NOTICE: "blue", - DEBUG: "gray", - SUCCESS: "green", -}; - -export const LOCAL_STORAGE_KEYS = { - CACHED_EVENTS: "cached_events", - THEME: "theme", - NAVBAR: "navbar", -}; - - -export enum SORT_ORDER { - ASC = 'asc', - DESC = 'desc', - DEFAULT = 'default', -} diff --git a/config/types.ts b/config/types.ts deleted file mode 100644 index f37df076..00000000 --- a/config/types.ts +++ /dev/null @@ -1,418 +0,0 @@ -import {EVENT_TYPES, ALL_EVENTS} from "~/config/constants"; - -export type OneOfValues = T[keyof T]; -export type EventId = string; -export type StatusCode = number; // TODO: update type -export type Email = string; // TODO: update type - -export type TEventType = OneOfValues; -export type TEventGroup = OneOfValues; - -type SMTPUser = { - name: string; - email: Email; -} - -export interface Monolog { - message: string, - context: object, - level: StatusCode, - level_name: string, - channel: string, - datetime: string, - extra: object, -} - -export interface SMTP { - id: string, - from: SMTPUser[], - reply_to: SMTPUser[], - subject: string, - to: SMTPUser[], - cc: SMTPUser[], - bcc: SMTPUser[], - text: string, - html: string, - raw: string, - attachments: unknown[] -} - -// TODO: Cover all possible cases -// https://github.com/getsentry/sentry/tree/master/static/app/components/events/contexts - -export type SentryFrame = { - filename: string, - lineno: number, - in_app: boolean, - abs_path: string, - pre_context: string[], - context_line: string, - post_context: string[] -} - -export type SentryException = { - type: string, - value: string, - stacktrace: { - frames: SentryFrame[] - }, - [key: string]: unknown -} - -export interface Sentry { - event_id: string, - timestamp: number, - platform: string, - contexts: { - runtime: { - name: string, - version: string, - } | unknown, - os: { - name: string, - version: string, - } | unknown, - app: { - device_app_hash: string, - build_type: string, - app_identifier: string, - app_name: string, - app_version: string, - app_build: string, - app_id: string, - type: string, - } | unknown, - device: { - screen_resolution: string, - orientation: string, - family: string, - battery_level: number, - screen_dpi: number, - memory_size: number, - timezone: string, - external_storage_size: number, - external_free_storage: number, - screen_width_pixels: number, - low_memory: boolean, - simulator: boolean, - screen_height_pixels: number, - free_memory: number, - online: boolean, - screen_density: number, - type: string, - charging: boolean, - model_id: string, - brand: string, - storage_size: number, - boot_time: string, - arch: string, - manufacturer: string, - name: string, // redacted - free_storage: number, - model: string, - } | unknown, - }, - breadcrumbs: { - values: [{ - type: string, - category: string, - level: string, - timestamp: number, - message: string, - }] - } | unknown, - sdk: { - name: string, - version: string, - } | unknown, - logger: string, - server_name: string, - environment: string, - modules: object, - extra: unknown, - tags: object, - request: { - url: string, - method: string, - headers: object, - data: object, - }, - exception: { - values: SentryException[] - } -} - -export interface VarDump { - payload: { - type: string, - value: string | number | boolean - }, - context: { - timestamp: number, - cli: { - command_line: string, - identifier: string - }, - source: { - name: string, - file: string, - line: number, - file_excerpt: boolean - } - } -} - -interface RayContentFrame { - file_name: string, - line_number: number, - class: string | null, - method: string, - vendor_frame: boolean, - snippet?: { line_number: number, text: string }[] -} -export interface RayContent { - content: string, - label: string, -} - -export interface RayContentCarbone { - formatted: string, - timestamp: number, - timezone: string -} - -export interface RayContentArray { - values: string[] | number[] | boolean[] -} - -export interface RayContentException { - class?: string, - message?: string, - frames: RayContentFrame[] -} -export interface RayContentSQL { - sql: string, - bindings: string[], - connection_name: string - time: number -} -export interface RayContentEloquent { - class_name: string, - attributes: string -} -export interface RayContentViews { - view_path: string, - view_path_relative_to_project_root: string, - data: string -} -export interface RayContentJobs { - event_name: string, - job: string, - exception: string | null -} - - -export interface RayPayload { - type: string, - origin?: { - file: string, - line_number: number, - hostname: string, - }, - content: RayContentException - | RayContentArray - | RayContent - | RayContentCarbone - | RayContentSQL - | RayContentEloquent - | RayContentViews - | RayContentJobs - | { frame: RayContentFrame } - | { value: string } - | { color: string } - | { label: string } - | { name: string } - | { size: string } - | never[] -} - -export interface RayDump { - uuid: string, - payloads: RayPayload[], - meta?: { - php_version: string, - php_version_id: number, - project_name: string, - laravel_version: string, - laravel_ray_package_version: string, - ray_package_version: string, - } -} - - -export interface SmtpAttachment { - name: string, - id: string, - uri: string, - size?: number, - mime?: string, -} - -export interface HttpDumpFile { - originalName: string, - mime: string, - size: number, -} - -export interface HttpDump { - received_at: string, - host: string, - request: { - method: string, - uri: string, - headers: { - [key: string]: string[] - }, - body: string, - query: any, - post: any, - cookies: { - [key: string]: string - }, - files: HttpDumpFile[] - } -} - -export interface ProfilerCost { - [key: string]: number, - - "ct": number, - "wt": number, - "cpu": number, - "mu": number, - "pmu": number -} - -export interface ProfilerEdge { - caller: string | null, - callee: string, - cost: ProfilerCost -} - -export type ProfilerEdges = Record - -export interface Profiler { - tags: { - [key: string]: string | null | number - }, - app_name: string, - hostname: string, - date: number, - peaks: ProfilerCost, - edges: ProfilerEdges -} - -export interface InspectorTransaction { - model: string, - name: string, - type: string, - hash: string, - host: { - hostname: string, - ip: string - os: string, - }, - http: { - request: { - method: string, - version: string, - socket: { - remote_address: string, - [key: string]: string - }, - cookies: { - [key: string]: string - }, - headers: { - [key: string]: string - } - }, - url: { - protocol: string, - port: number | string, - path: string, - search: string, - full: string, - }, - }, - result: string, - timestamp: number, - memory_peak: number, - duration: number, -} - -export interface InspectorSegment { - model: string, - type: string, - label: string, - host: { - hostname: string, - ip: string - os: string, - }, - transaction: { - name: string, - timestamp: number, - }, - start: number, - timestamp: number, - context: object - duration: number, -} - -export type Inspector = InspectorTransaction[] | InspectorSegment[]; - -export interface ServerEvent { - uuid: EventId, - type: TEventType | string, - payload: T, - project_id: string | null, - timestamp?: number // unavailable for some ray dump events -} - -export interface NormalizedEvent { - id: EventId, - type: TEventType | string, - labels: string[], - origin: object | null, - serverName: string, - date: Date, - payload: Monolog | SMTP | Sentry | VarDump | Profiler | Inspector | HttpDump | RayDump | unknown -} - -export type TGraphNode = { - data: { - id: string, - name: string, - cost?: ProfilerCost, - color?: string, - textColor?: string - } -} - -export type TGraphEdge = { - data: { - id?: string, - source: string, - target: string, - label?: string, - color?: string, - } -} - -export enum GraphTypes { - CPU = 'cpu', - MEMORY_CHANGE = 'pmu', - MEMORY = 'mu', - CALLS = 'calls' -} diff --git a/layouts/default.vue b/layouts/default.vue index 944a405a..6a61116c 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -13,7 +13,7 @@ + + + + diff --git a/src/entities/inspector/index.ts b/src/entities/inspector/index.ts new file mode 100644 index 00000000..2d99edf3 --- /dev/null +++ b/src/entities/inspector/index.ts @@ -0,0 +1,2 @@ +export * from './ui'; +export * from './lib'; diff --git a/src/entities/inspector/lib/index.ts b/src/entities/inspector/lib/index.ts new file mode 100644 index 00000000..cad2fc87 --- /dev/null +++ b/src/entities/inspector/lib/index.ts @@ -0,0 +1 @@ +export * from './use-inspector' diff --git a/src/entities/inspector/lib/use-inspector/index.ts b/src/entities/inspector/lib/use-inspector/index.ts new file mode 100644 index 00000000..1cbc08e2 --- /dev/null +++ b/src/entities/inspector/lib/use-inspector/index.ts @@ -0,0 +1,2 @@ +export * from "./use-inspector"; + diff --git a/src/entities/inspector/lib/use-inspector/normalize-inspector-event.ts b/src/entities/inspector/lib/use-inspector/normalize-inspector-event.ts new file mode 100644 index 00000000..d3395cf7 --- /dev/null +++ b/src/entities/inspector/lib/use-inspector/normalize-inspector-event.ts @@ -0,0 +1,16 @@ +import { EVENT_TYPES, ServerEvent, NormalizedEvent } from "~/src/shared/types"; +import { Inspector, InspectorTransaction } from "../../types"; + +export const normalizeInspectorEvent = (event: ServerEvent): NormalizedEvent => { + const transaction = event.payload[0] as InspectorTransaction; + + return { + id: event.uuid, + type: EVENT_TYPES.INSPECTOR, + labels: [EVENT_TYPES.INSPECTOR], + origin: {name: transaction.host.hostname, ip: transaction.host.ip, os: transaction.host.os}, + serverName: transaction.host.hostname, + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload + } +} diff --git a/src/entities/inspector/lib/use-inspector/use-inspector.ts b/src/entities/inspector/lib/use-inspector/use-inspector.ts new file mode 100644 index 00000000..9df4cb54 --- /dev/null +++ b/src/entities/inspector/lib/use-inspector/use-inspector.ts @@ -0,0 +1,11 @@ +import { ServerEvent, NormalizedEvent } from '~/src/shared/types'; +import { Inspector } from "../../types"; +import { normalizeInspectorEvent } from "./normalize-inspector-event"; + +type TUseInspector = () => { + normalizeInspectorEvent: (event: ServerEvent) => NormalizedEvent +} + +export const useInspector: TUseInspector = () => ({ + normalizeInspectorEvent +}) diff --git a/src/entities/inspector/mocks/index.ts b/src/entities/inspector/mocks/index.ts new file mode 100644 index 00000000..f6a4653d --- /dev/null +++ b/src/entities/inspector/mocks/index.ts @@ -0,0 +1,5 @@ +import inspectorMock from './inspector.json'; + +export { + inspectorMock, +} diff --git a/mocks/inspector.json b/src/entities/inspector/mocks/inspector.json similarity index 100% rename from mocks/inspector.json rename to src/entities/inspector/mocks/inspector.json diff --git a/src/entities/inspector/types.ts b/src/entities/inspector/types.ts new file mode 100644 index 00000000..57e0e3cb --- /dev/null +++ b/src/entities/inspector/types.ts @@ -0,0 +1,61 @@ +export interface InspectorTransaction { + model: 'transaction' | string, + name?: string, + type: string, + hash?: string, + host: { + hostname: string, + ip: string + os: string, + }, + http?: { + request: { + method: string, + version: string, + socket: { + remote_address: string, + [key: string]: string + }, + cookies: { + [key: string]: string + }, + headers: { + [key: string]: string + } + }, + url: { + protocol: string, + port: number | string, + path: string, + search: string, + full: string, + }, + }, + result?: string, + timestamp: number, + memory_peak?: number, + duration: number, +} + +export interface InspectorSegment { + model: 'segment' | string, + type: string, + label?: string, + host: { + hostname: string, + ip: string + os: string, + }, + transaction?: { + name: string, + timestamp: number, + hash: string, + }, + start?: number, + timestamp: number, + context: object + duration: number, + name?: string, +} + +export type Inspector = InspectorTransaction[] | InspectorSegment[]; diff --git a/src/entities/inspector/ui/index.ts b/src/entities/inspector/ui/index.ts new file mode 100644 index 00000000..b06bf0eb --- /dev/null +++ b/src/entities/inspector/ui/index.ts @@ -0,0 +1,2 @@ +export * from './preview-card'; +export * from './inspector-stat-board'; diff --git a/src/entities/inspector/ui/inspector-stat-board/index.ts b/src/entities/inspector/ui/inspector-stat-board/index.ts new file mode 100644 index 00000000..90231bfe --- /dev/null +++ b/src/entities/inspector/ui/inspector-stat-board/index.ts @@ -0,0 +1,3 @@ +import InspectorStatBoard from './inspector-stat-board.vue' + +export { InspectorStatBoard }; diff --git a/components/InspectorStatBoard/InspectorStatBoard.stories.ts b/src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.stories.ts similarity index 54% rename from components/InspectorStatBoard/InspectorStatBoard.stories.ts rename to src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.stories.ts index 49021903..e540cc31 100644 --- a/components/InspectorStatBoard/InspectorStatBoard.stories.ts +++ b/src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.stories.ts @@ -1,10 +1,12 @@ import {Meta, Story} from "@storybook/vue3"; -import {normalizeInspectorEvent} from "~/utils/normalize-event"; -import inspectorEventMock from '~/mocks/inspector.json' -import InspectorStatBoard from '~/components/InspectorStatBoard/InspectorStatBoard.vue'; +import { useInspector } from "../../lib"; +import { inspectorMock } from '../../mocks' +import InspectorStatBoard from './inspector-stat-board.vue'; + +const { normalizeInspectorEvent } = useInspector(); export default { - title: "Inspector/Components/InspectorStatBoard", + title: "Entities/inspector/InspectorStatBoard", component: InspectorStatBoard } as Meta; @@ -21,5 +23,5 @@ const Template: Story = (args) => ({ export const StatBoardStories = Template.bind({}); StatBoardStories.args = { - transaction: normalizeInspectorEvent(inspectorEventMock).payload[0] + transaction: normalizeInspectorEvent(inspectorMock).payload[0] }; diff --git a/components/InspectorStatBoard/InspectorStatBoard.vue b/src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.vue similarity index 63% rename from components/InspectorStatBoard/InspectorStatBoard.vue rename to src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.vue index 2a586c95..99f94fb0 100644 --- a/components/InspectorStatBoard/InspectorStatBoard.vue +++ b/src/entities/inspector/ui/inspector-stat-board/inspector-stat-board.vue @@ -1,17 +1,38 @@ + + - - diff --git a/src/entities/monolog/index.ts b/src/entities/monolog/index.ts new file mode 100644 index 00000000..03a8d531 --- /dev/null +++ b/src/entities/monolog/index.ts @@ -0,0 +1,2 @@ +export * from './lib'; +export * from './ui'; diff --git a/src/entities/monolog/lib/index.ts b/src/entities/monolog/lib/index.ts new file mode 100644 index 00000000..ef0b1fed --- /dev/null +++ b/src/entities/monolog/lib/index.ts @@ -0,0 +1 @@ +export * from './use-monolog'; diff --git a/src/entities/monolog/lib/use-monolog/index.ts b/src/entities/monolog/lib/use-monolog/index.ts new file mode 100644 index 00000000..35f528e9 --- /dev/null +++ b/src/entities/monolog/lib/use-monolog/index.ts @@ -0,0 +1,2 @@ +export * from "./use-monolog"; + diff --git a/src/entities/monolog/lib/use-monolog/normalize-monolog.ts b/src/entities/monolog/lib/use-monolog/normalize-monolog.ts new file mode 100644 index 00000000..654c0291 --- /dev/null +++ b/src/entities/monolog/lib/use-monolog/normalize-monolog.ts @@ -0,0 +1,16 @@ +import { EVENT_TYPES, ServerEvent, NormalizedEvent } from "~/src/shared/types"; +import { Monolog } from "../../types"; + +export const normalizeMonolog = (event: ServerEvent): NormalizedEvent => { + const origin = event.payload?.context?.source || null; + + return { + id: event.uuid, + type: EVENT_TYPES.VAR_DUMP, + labels: [EVENT_TYPES.VAR_DUMP], + origin, + serverName: "", + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload + } +} diff --git a/src/entities/monolog/lib/use-monolog/use-monolog.ts b/src/entities/monolog/lib/use-monolog/use-monolog.ts new file mode 100644 index 00000000..65f9818c --- /dev/null +++ b/src/entities/monolog/lib/use-monolog/use-monolog.ts @@ -0,0 +1,11 @@ +import { ServerEvent, NormalizedEvent } from '~/src/shared/types'; +import { Monolog } from "../../types"; +import { normalizeMonolog } from "./normalize-monolog"; + +type TUseMonolog = () => { + normalizeMonologEvent: (event: ServerEvent) => NormalizedEvent +} + +export const useMonolog: TUseMonolog = () => ({ + normalizeMonologEvent: normalizeMonolog +}) diff --git a/src/entities/monolog/mocks/index.ts b/src/entities/monolog/mocks/index.ts new file mode 100644 index 00000000..556a09e1 --- /dev/null +++ b/src/entities/monolog/mocks/index.ts @@ -0,0 +1,5 @@ +import monologMock from './monolog.json'; + +export { + monologMock, +} diff --git a/mocks/monolog.json b/src/entities/monolog/mocks/monolog.json similarity index 100% rename from mocks/monolog.json rename to src/entities/monolog/mocks/monolog.json diff --git a/src/entities/monolog/types.ts b/src/entities/monolog/types.ts new file mode 100644 index 00000000..139730c6 --- /dev/null +++ b/src/entities/monolog/types.ts @@ -0,0 +1,17 @@ +import { Source } from "~/src/shared/types"; + +export type StatusCode = number; // TODO: update type + +export interface Monolog { + message: string, + context: { + source?: Source, + [key: string]: unknown + }, + level: StatusCode, + level_name: string, + channel: string, + datetime: string, + extra: object, +} + diff --git a/src/entities/monolog/ui/index.ts b/src/entities/monolog/ui/index.ts new file mode 100644 index 00000000..52b27d6b --- /dev/null +++ b/src/entities/monolog/ui/index.ts @@ -0,0 +1 @@ +export * from './preview-card'; diff --git a/src/entities/monolog/ui/preview-card/index.ts b/src/entities/monolog/ui/preview-card/index.ts new file mode 100644 index 00000000..7f59f151 --- /dev/null +++ b/src/entities/monolog/ui/preview-card/index.ts @@ -0,0 +1,3 @@ +import PreviewCard from './preview-card.vue'; + +export { PreviewCard }; diff --git a/src/entities/monolog/ui/preview-card/preview-card.stories.ts b/src/entities/monolog/ui/preview-card/preview-card.stories.ts new file mode 100644 index 00000000..01132405 --- /dev/null +++ b/src/entities/monolog/ui/preview-card/preview-card.stories.ts @@ -0,0 +1,40 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useMonolog } from "../../lib"; +import { monologMock } from '../../mocks' +import PreviewCard from './preview-card.vue'; + +const { normalizeMonologEvent } = useMonolog(); + +export default { + title: "Entities/monolog/PreviewCard", + component: PreviewCard +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Event = Template.bind({}); + +Event.args = { + event: normalizeMonologEvent(monologMock), +}; + +export const WithOrigin = Template.bind({}); + +WithOrigin.args = { + event: { + ...normalizeMonologEvent(monologMock), + origin: { + file: "/var/www/html/vendor/symfony/http-kernel/HttpKernel.php", + line_number: 151, + name: "Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw", + } + }, +}; diff --git a/src/entities/monolog/ui/preview-card/preview-card.vue b/src/entities/monolog/ui/preview-card/preview-card.vue new file mode 100644 index 00000000..8bda6c91 --- /dev/null +++ b/src/entities/monolog/ui/preview-card/preview-card.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/entities/profiler/index.ts b/src/entities/profiler/index.ts new file mode 100644 index 00000000..03a8d531 --- /dev/null +++ b/src/entities/profiler/index.ts @@ -0,0 +1,2 @@ +export * from './lib'; +export * from './ui'; diff --git a/src/entities/profiler/lib/index.ts b/src/entities/profiler/lib/index.ts new file mode 100644 index 00000000..367bf5b9 --- /dev/null +++ b/src/entities/profiler/lib/index.ts @@ -0,0 +1 @@ +export * from './use-profiler'; diff --git a/src/entities/profiler/lib/use-profiler/index.ts b/src/entities/profiler/lib/use-profiler/index.ts new file mode 100644 index 00000000..7a55f667 --- /dev/null +++ b/src/entities/profiler/lib/use-profiler/index.ts @@ -0,0 +1,2 @@ +export * from "./use-profiler"; + diff --git a/src/entities/profiler/lib/use-profiler/normalize-profile-event.ts b/src/entities/profiler/lib/use-profiler/normalize-profile-event.ts new file mode 100644 index 00000000..6172d3db --- /dev/null +++ b/src/entities/profiler/lib/use-profiler/normalize-profile-event.ts @@ -0,0 +1,12 @@ +import { EVENT_TYPES, ServerEvent, NormalizedEvent } from "~/src/shared/types"; +import { Profiler } from "../../types"; + +export const normalizeProfilerEvent = (event: ServerEvent): NormalizedEvent => ({ + id: event.uuid, + type: EVENT_TYPES.PROFILER, + labels: [EVENT_TYPES.PROFILER], + origin: {name: event.payload.app_name, ...event.payload.tags}, + serverName: event.payload.hostname, + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload +}) diff --git a/src/entities/profiler/lib/use-profiler/use-profiler.ts b/src/entities/profiler/lib/use-profiler/use-profiler.ts new file mode 100644 index 00000000..b80b66ff --- /dev/null +++ b/src/entities/profiler/lib/use-profiler/use-profiler.ts @@ -0,0 +1,11 @@ +import { ServerEvent, NormalizedEvent } from '~/src/shared/types'; +import { Profiler } from "../../types"; +import { normalizeProfilerEvent } from "./normalize-profile-event"; + +type TUseProfiler = () => { + normalizeProfilerEvent: (event: ServerEvent) => NormalizedEvent +} + +export const useProfiler: TUseProfiler = () => ({ + normalizeProfilerEvent +}) diff --git a/src/entities/profiler/mocks/index.ts b/src/entities/profiler/mocks/index.ts new file mode 100644 index 00000000..819a5e00 --- /dev/null +++ b/src/entities/profiler/mocks/index.ts @@ -0,0 +1,5 @@ +import profilerMock from './profiler.json'; + +export { + profilerMock, +} diff --git a/mocks/profiler.json b/src/entities/profiler/mocks/profiler.json similarity index 100% rename from mocks/profiler.json rename to src/entities/profiler/mocks/profiler.json diff --git a/src/entities/profiler/types.ts b/src/entities/profiler/types.ts new file mode 100644 index 00000000..45c6b4b7 --- /dev/null +++ b/src/entities/profiler/types.ts @@ -0,0 +1,26 @@ +export interface ProfilerCost { + [key: string]: number, + "ct": number, + "wt": number, + "cpu": number, + "mu": number, + "pmu": number +} +export interface ProfilerEdge { + caller: string | null, + callee: string, + cost: ProfilerCost +} + +export type ProfilerEdges = Record + +export interface Profiler { + tags: { + [key: string]: string | null | number + }, + app_name: string, + hostname: string, + date: number, + peaks: ProfilerCost, + edges: ProfilerEdges +} diff --git a/src/entities/profiler/ui/index.ts b/src/entities/profiler/ui/index.ts new file mode 100644 index 00000000..7f760c0c --- /dev/null +++ b/src/entities/profiler/ui/index.ts @@ -0,0 +1 @@ +export * from './preview-card' diff --git a/src/entities/profiler/ui/preview-card/index.ts b/src/entities/profiler/ui/preview-card/index.ts new file mode 100644 index 00000000..7f59f151 --- /dev/null +++ b/src/entities/profiler/ui/preview-card/index.ts @@ -0,0 +1,3 @@ +import PreviewCard from './preview-card.vue'; + +export { PreviewCard }; diff --git a/src/entities/profiler/ui/preview-card/preview-card.stories.ts b/src/entities/profiler/ui/preview-card/preview-card.stories.ts new file mode 100644 index 00000000..62a10928 --- /dev/null +++ b/src/entities/profiler/ui/preview-card/preview-card.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useProfiler } from "../../lib"; +import { profilerMock } from "../../mocks"; +import PreviewCard from './preview-card.vue'; + +const { normalizeProfilerEvent } = useProfiler(); + +export default { + title: "Entities/profiler/PreviewCard", + component: PreviewCard +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Event = Template.bind({}); + +Event.args = { + event: normalizeProfilerEvent(profilerMock), +}; diff --git a/src/entities/profiler/ui/preview-card/preview-card.vue b/src/entities/profiler/ui/preview-card/preview-card.vue new file mode 100644 index 00000000..779bfa5d --- /dev/null +++ b/src/entities/profiler/ui/preview-card/preview-card.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/entities/ray/index.ts b/src/entities/ray/index.ts new file mode 100644 index 00000000..03a8d531 --- /dev/null +++ b/src/entities/ray/index.ts @@ -0,0 +1,2 @@ +export * from './lib'; +export * from './ui'; diff --git a/src/entities/ray/lib/index.ts b/src/entities/ray/lib/index.ts new file mode 100644 index 00000000..a1102694 --- /dev/null +++ b/src/entities/ray/lib/index.ts @@ -0,0 +1 @@ +export * from './use-ray' diff --git a/src/entities/ray/lib/use-ray/index.ts b/src/entities/ray/lib/use-ray/index.ts new file mode 100644 index 00000000..922bf2df --- /dev/null +++ b/src/entities/ray/lib/use-ray/index.ts @@ -0,0 +1,2 @@ +export * from "./use-ray"; + diff --git a/src/entities/ray/lib/use-ray/normalize-ray-event.ts b/src/entities/ray/lib/use-ray/normalize-ray-event.ts new file mode 100644 index 00000000..c36a6e94 --- /dev/null +++ b/src/entities/ray/lib/use-ray/normalize-ray-event.ts @@ -0,0 +1,56 @@ +import pick from "lodash/pick"; +import { EVENT_TYPES, ServerEvent } from "~/src/shared/types"; +import { EnhancedRayEvent, RayContentColor, RayContentLabel, RayContentSize, RayDump, RAY_EVENT_TYPES } from "../../types"; + +export const normalizeRayEvent = (event: ServerEvent): EnhancedRayEvent => { + let origin = { + php_version: event.payload.meta?.php_version, + laravel_version: event.payload.meta?.laravel_version, + } + + event.payload.payloads + .forEach(payload => { + if (payload.origin) { + origin = { + ...origin, + ...pick(payload.origin, ['file', 'line_number', 'hostname']), + } + } + }) + + const labels = event.payload.payloads + .filter(payload => payload.type === 'label') + .map(payload => (payload?.content as RayContentLabel)?.label) + .filter(Boolean) + + const typeLabels = event.payload.payloads + .filter(payload => Object.values(RAY_EVENT_TYPES).includes(payload.type as RAY_EVENT_TYPES)) + .map(payload => payload.type) + .filter(Boolean) + + const color = event.payload.payloads + .filter(payload => payload.type === 'color') + .map(payload => (payload.content as RayContentColor)?.color) + .filter(Boolean) + .shift() || 'black' + + const size = (event.payload.payloads + .filter(payload => payload.type === 'size') + .map(payload => (payload.content as RayContentSize)?.size) + .filter(Boolean) + .shift() || 'md') as EnhancedRayEvent['meta']['size'] + + return { + id: event.uuid, + type: EVENT_TYPES.RAY_DUMP, + labels: [EVENT_TYPES.RAY_DUMP, ...labels, ...typeLabels].filter((x, i, a) => a.indexOf(x) === i), + origin, + serverName: "", + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload, + meta: { + color, + size + } + } +} diff --git a/src/entities/ray/lib/use-ray/use-ray.ts b/src/entities/ray/lib/use-ray/use-ray.ts new file mode 100644 index 00000000..6aa58687 --- /dev/null +++ b/src/entities/ray/lib/use-ray/use-ray.ts @@ -0,0 +1,11 @@ +import { ServerEvent } from '~/src/shared/types'; +import { EnhancedRayEvent, RayDump } from "../../types"; +import { normalizeRayEvent } from "./normalize-ray-event"; + +type TUseRay = () => { + normalizeRayEvent: (event: ServerEvent) => EnhancedRayEvent +} + +export const useRay: TUseRay = () => ({ + normalizeRayEvent +}) diff --git a/src/entities/ray/mocks-laravel/index.ts b/src/entities/ray/mocks-laravel/index.ts new file mode 100644 index 00000000..f9178c38 --- /dev/null +++ b/src/entities/ray/mocks-laravel/index.ts @@ -0,0 +1,23 @@ +import rayLaravelCacheMock from './ray-laravel-cache.json'; +import rayLaravelCollectionMock from './ray-laravel-collections.json'; +import rayLaravelEloquentMock from './ray-laravel-eloquent.json'; +import rayLaravelEventsMock from './ray-laravel-events.json'; +import rayLaravelHttpRequestMock from './ray-laravel-http-request.json'; +import rayLaravelJobsMock from './ray-laravel-jobs.json'; +import rayLaravelMailableMock from './ray-laravel-mailable.json'; +import rayLaravelQueryNoBindingsMock from './ray-laravel-query-no-bindings.json'; +import rayLaravelQueryMock from './ray-laravel-query.json'; +import rayLaravelViewsMock from './ray-laravel-views.json'; + +export { + rayLaravelCacheMock, + rayLaravelCollectionMock, + rayLaravelEloquentMock, + rayLaravelJobsMock, + rayLaravelEventsMock, + rayLaravelHttpRequestMock, + rayLaravelMailableMock, + rayLaravelQueryMock, + rayLaravelQueryNoBindingsMock, + rayLaravelViewsMock +} diff --git a/mocks/ray-laravel-cache.json b/src/entities/ray/mocks-laravel/ray-laravel-cache.json similarity index 100% rename from mocks/ray-laravel-cache.json rename to src/entities/ray/mocks-laravel/ray-laravel-cache.json diff --git a/mocks/ray-laravel-collections.json b/src/entities/ray/mocks-laravel/ray-laravel-collections.json similarity index 99% rename from mocks/ray-laravel-collections.json rename to src/entities/ray/mocks-laravel/ray-laravel-collections.json index 761a8bfc..c8a0e05e 100644 --- a/mocks/ray-laravel-collections.json +++ b/src/entities/ray/mocks-laravel/ray-laravel-collections.json @@ -7,9 +7,7 @@ { "type": "log", "content": { - "values": [ - "uppercased collection" - ] + "values": ["uppercased collection"] }, "origin": { "file": "/root/repos/buggreagtor/examples/app/Modules/Ray/RayLaravel.php", diff --git a/mocks/ray-laravel-eloquent.json b/src/entities/ray/mocks-laravel/ray-laravel-eloquent.json similarity index 100% rename from mocks/ray-laravel-eloquent.json rename to src/entities/ray/mocks-laravel/ray-laravel-eloquent.json diff --git a/mocks/ray-laravel-events.json b/src/entities/ray/mocks-laravel/ray-laravel-events.json similarity index 100% rename from mocks/ray-laravel-events.json rename to src/entities/ray/mocks-laravel/ray-laravel-events.json diff --git a/mocks/ray-laravel-http-request.json b/src/entities/ray/mocks-laravel/ray-laravel-http-request.json similarity index 100% rename from mocks/ray-laravel-http-request.json rename to src/entities/ray/mocks-laravel/ray-laravel-http-request.json diff --git a/mocks/ray-laravel-jobs.json b/src/entities/ray/mocks-laravel/ray-laravel-jobs.json similarity index 100% rename from mocks/ray-laravel-jobs.json rename to src/entities/ray/mocks-laravel/ray-laravel-jobs.json diff --git a/mocks/ray-laravel-mailable.json b/src/entities/ray/mocks-laravel/ray-laravel-mailable.json similarity index 100% rename from mocks/ray-laravel-mailable.json rename to src/entities/ray/mocks-laravel/ray-laravel-mailable.json diff --git a/mocks/ray-laravel-query-no-bindings.json b/src/entities/ray/mocks-laravel/ray-laravel-query-no-bindings.json similarity index 100% rename from mocks/ray-laravel-query-no-bindings.json rename to src/entities/ray/mocks-laravel/ray-laravel-query-no-bindings.json diff --git a/mocks/ray-laravel-query.json b/src/entities/ray/mocks-laravel/ray-laravel-query.json similarity index 92% rename from mocks/ray-laravel-query.json rename to src/entities/ray/mocks-laravel/ray-laravel-query.json index 61d67be0..56397d68 100644 --- a/mocks/ray-laravel-query.json +++ b/src/entities/ray/mocks-laravel/ray-laravel-query.json @@ -8,9 +8,7 @@ "type": "executed_query", "content": { "sql": "select * from \"users\" where \"email\" = ? limit 1", - "bindings": [ - "john@example.com" - ], + "bindings": ["john@example.com"], "connection_name": "sqlite", "time": 0.38 }, diff --git a/mocks/ray-laravel-views.json b/src/entities/ray/mocks-laravel/ray-laravel-views.json similarity index 100% rename from mocks/ray-laravel-views.json rename to src/entities/ray/mocks-laravel/ray-laravel-views.json diff --git a/src/entities/ray/mocks/index.ts b/src/entities/ray/mocks/index.ts new file mode 100644 index 00000000..99e82586 --- /dev/null +++ b/src/entities/ray/mocks/index.ts @@ -0,0 +1,43 @@ +import rayCallerMock from './ray-caller.json'; +import rayCarbonMock from './ray-carbon.json'; +import rayColorMock from './ray-color.json'; +import rayCounterMock from './ray-counter.json'; +import rayDumpMock from './ray-dump.json'; +import rayEmptyStringMock from './ray-empty-string.json'; +import rayExceptionMock from './ray-exception.json'; +import rayHideMock from './ray-hide.json'; +import rayImageMock from './ray-image.json'; +import rayIntegerMock from './ray-integer.json'; +import rayJsonMock from './ray-json.json'; +import rayLabelMock from './ray-label.json'; +import rayLockMock from './ray-lock.json'; +import rayMeasureStartMock from './ray-measure-start.json'; +import rayMeasureMock from './ray-measure.json'; +import rayNotifyMock from './ray-notify.json'; +import raySizeMock from './ray-size.json'; +import rayTableMock from './ray-table.json'; +import rayTextMock from './ray-text.json'; +import rayTraceMock from './ray-trace.json'; + +export { + rayCallerMock, + rayCarbonMock, + rayColorMock, + rayCounterMock, + rayDumpMock, + rayExceptionMock, + rayEmptyStringMock, + rayHideMock, + rayImageMock, + rayIntegerMock, + rayJsonMock, + rayLabelMock, + rayLockMock, + rayMeasureMock, + rayMeasureStartMock, + rayNotifyMock, + raySizeMock, + rayTableMock, + rayTextMock, + rayTraceMock, +} diff --git a/mocks/ray-caller.json b/src/entities/ray/mocks/ray-caller.json similarity index 100% rename from mocks/ray-caller.json rename to src/entities/ray/mocks/ray-caller.json diff --git a/mocks/ray-carbon.json b/src/entities/ray/mocks/ray-carbon.json similarity index 100% rename from mocks/ray-carbon.json rename to src/entities/ray/mocks/ray-carbon.json diff --git a/mocks/ray-color.json b/src/entities/ray/mocks/ray-color.json similarity index 94% rename from mocks/ray-color.json rename to src/entities/ray/mocks/ray-color.json index fe9a8190..dae44393 100644 --- a/mocks/ray-color.json +++ b/src/entities/ray/mocks/ray-color.json @@ -7,9 +7,7 @@ { "type": "log", "content": { - "values": [ - "this is green" - ] + "values": ["this is green"] }, "origin": { "file": "/root/repos/buggreagtor/examples/app/Modules/Ray/RayCommon.php", diff --git a/mocks/ray-counter.json b/src/entities/ray/mocks/ray-counter.json similarity index 100% rename from mocks/ray-counter.json rename to src/entities/ray/mocks/ray-counter.json diff --git a/mocks/ray-dump.json b/src/entities/ray/mocks/ray-dump.json similarity index 100% rename from mocks/ray-dump.json rename to src/entities/ray/mocks/ray-dump.json diff --git a/mocks/ray-github-issue-44.json b/src/entities/ray/mocks/ray-empty-string.json similarity index 100% rename from mocks/ray-github-issue-44.json rename to src/entities/ray/mocks/ray-empty-string.json diff --git a/mocks/ray-exception.json b/src/entities/ray/mocks/ray-exception.json similarity index 100% rename from mocks/ray-exception.json rename to src/entities/ray/mocks/ray-exception.json diff --git a/mocks/ray-hide.json b/src/entities/ray/mocks/ray-hide.json similarity index 100% rename from mocks/ray-hide.json rename to src/entities/ray/mocks/ray-hide.json diff --git a/mocks/ray-image.json b/src/entities/ray/mocks/ray-image.json similarity index 100% rename from mocks/ray-image.json rename to src/entities/ray/mocks/ray-image.json diff --git a/mocks/ray-int.json b/src/entities/ray/mocks/ray-integer.json similarity index 99% rename from mocks/ray-int.json rename to src/entities/ray/mocks/ray-integer.json index 9da2b1a5..91fcf5a2 100644 --- a/mocks/ray-int.json +++ b/src/entities/ray/mocks/ray-integer.json @@ -127,6 +127,3 @@ "timestamp": 1673266869, "project_id": null } - - - diff --git a/mocks/ray-json.json b/src/entities/ray/mocks/ray-json.json similarity index 100% rename from mocks/ray-json.json rename to src/entities/ray/mocks/ray-json.json diff --git a/mocks/ray-label.json b/src/entities/ray/mocks/ray-label.json similarity index 100% rename from mocks/ray-label.json rename to src/entities/ray/mocks/ray-label.json diff --git a/mocks/ray-lock.json b/src/entities/ray/mocks/ray-lock.json similarity index 88% rename from mocks/ray-lock.json rename to src/entities/ray/mocks/ray-lock.json index 7fc7b21f..afb388ad 100644 --- a/mocks/ray-lock.json +++ b/src/entities/ray/mocks/ray-lock.json @@ -10,7 +10,7 @@ "name": "07c1878459f801740304771cd63993c7" }, "origin": { - "file": "\/root\/repos\/buggreagtor\/examples\/app\/Modules\/Ray\/RayCommon.php", + "file": "/root/repos/buggreagtor/examples/app/Modules/Ray/RayCommon.php", "line_number": 102, "hostname": "ButschsterLpp" } diff --git a/mocks/ray-measure-start.json b/src/entities/ray/mocks/ray-measure-start.json similarity index 100% rename from mocks/ray-measure-start.json rename to src/entities/ray/mocks/ray-measure-start.json diff --git a/mocks/ray-measure.json b/src/entities/ray/mocks/ray-measure.json similarity index 100% rename from mocks/ray-measure.json rename to src/entities/ray/mocks/ray-measure.json diff --git a/mocks/ray-notify.json b/src/entities/ray/mocks/ray-notify.json similarity index 100% rename from mocks/ray-notify.json rename to src/entities/ray/mocks/ray-notify.json diff --git a/mocks/ray-size.json b/src/entities/ray/mocks/ray-size.json similarity index 100% rename from mocks/ray-size.json rename to src/entities/ray/mocks/ray-size.json diff --git a/mocks/ray-table.json b/src/entities/ray/mocks/ray-table.json similarity index 100% rename from mocks/ray-table.json rename to src/entities/ray/mocks/ray-table.json diff --git a/mocks/ray-text.json b/src/entities/ray/mocks/ray-text.json similarity index 100% rename from mocks/ray-text.json rename to src/entities/ray/mocks/ray-text.json diff --git a/mocks/ray-trace.json b/src/entities/ray/mocks/ray-trace.json similarity index 100% rename from mocks/ray-trace.json rename to src/entities/ray/mocks/ray-trace.json diff --git a/src/entities/ray/types.ts b/src/entities/ray/types.ts new file mode 100644 index 00000000..2827d276 --- /dev/null +++ b/src/entities/ray/types.ts @@ -0,0 +1,204 @@ +import { NormalizedEvent } from "~/src/shared/types"; + +export interface RayFrame { + file_name: string, + line_number: number, + class: string | null, + method: string, + vendor_frame: boolean, + snippet?: { line_number: number, text: string }[] +} + +export interface RayPayloadOrigin { + file: string, + line_number: number, + hostname: string, +} + +export interface RayContent { + content: string, + label: string, +} + +export interface RayContentCarbone { + formatted: string, + timestamp: number, + timezone: string +} + +export interface RayContentArray { + values: string[] | number[] | boolean[] +} + +export interface RayContentObject { + values: { + [key: string]: string + } +} + +export interface RayContentException { + class?: string, + message?: string, + frames: RayFrame[] +} + +export interface RayContentSQL { + sql: string, + bindings?: string[], + connection_name: string + time: number +} + +export interface RayContentEloquent { + class_name: string, + attributes: string +} + +export interface RayContentView { + view_path: string, + view_path_relative_to_project_root: string, + data: string +} + +export interface RayContentJob { + event_name: string, + job: string, + exception: string | null +} + +export interface RayContentLabel { + label: string, + [key: string]: unknown +} + +export interface RayContentColor { + color: string, + [key: string]: unknown +} + +export interface RayContentSize { + size: string, + [key: string]: unknown +} + +export interface RayContentFrame { + frame: RayFrame +} + +export interface RayContentFrames { + frames: RayFrame[] +} + +export interface RayContentMeasure { + name: string, + is_new_timer: boolean, + total_time: number, + max_memory_usage_during_total_time: number, + time_since_last_call: number, + max_memory_usage_since_last_call: number +} + +export interface RayUser { + name: string, + email: string, +} + +export interface RayContentMail { + subject: string, + from: RayUser[], + to: RayUser[], + cc?: RayUser[], + bcc?: RayUser[], + reply_to?: RayUser[], + mailable_class?: string, + html: string +} +export interface RayContentLog { + values: string[] | number[] +} + +export interface RayContentEvent { + name: string, + event: string, + payload: unknown, + class_based_event: boolean +} + +export interface RayContentLock { + name: string, +} + +export interface RayContentCustom { + content?: string, + label?: string, +} + +export interface RayPayload { + type: string, + origin?: RayPayloadOrigin, + content: RayContentException + | RayContent + | RayContentArray + | RayContentObject + | RayContentCarbone + | RayContentSQL + | RayContentEloquent + | RayContentView + | RayContentJob + | RayContentFrame + | RayContentFrames + | RayContentMeasure + | RayContentMail + | RayContentLog + | RayContentEvent + | RayContentCustom + | { value: string } + | RayContentColor + | RayContentLabel + | RayContentLock + | RayContentSize + | unknown[] +} + +export interface RayDump { + uuid: string, + payloads: RayPayload[], + meta?: { + php_version: string, + php_version_id: number, + project_name: string, + laravel_version: string, + laravel_ray_package_version: string, + ray_package_version: string, + } +} + +export interface EnhancedRayEvent extends NormalizedEvent { + meta: { + color: string, + size: 'sm' | 'md' | 'lg' | 'xl', + } +} + +export enum RAY_EVENT_TYPES { + LOG = "log", + // SIZE = "size", + CUSTOM = "custom", + // LABEL = "label", + CALLER = "caller", + CARBON = "carbon", + // COLOR = "color", + EXCEPTION = "exception", + // HIDE = "hide", + MEASURE = "measure", + NOTIFY = "notify", + MAILABLE = "mailable", + TABLE = "table", + TRACE = "trace", + QUERY = "executed_query", + ELOQUENT = "eloquent_model", + VIEW = "view", + EVENT = "event", + JOB = "job_event", + LOCK = "create_lock", +} diff --git a/src/entities/ray/ui/index.ts b/src/entities/ray/ui/index.ts new file mode 100644 index 00000000..8b9d2f2f --- /dev/null +++ b/src/entities/ray/ui/index.ts @@ -0,0 +1,18 @@ +export * from './ray-frame'; +export * from './ray-carbone'; +export * from './ray-exception'; +export * from './ray-file'; +export * from './ray-trace'; +export * from './ray-origin'; +export * from './ray-measure'; +export * from './ray-table'; +export * from './ray-mail'; +export * from './ray-log'; +export * from './ray-view'; +export * from './ray-job'; +export * from './ray-eloquent'; +export * from './ray-query'; +export * from './ray-event'; +export * from './ray-lock'; +export * from './ray-custom'; +export * from './preview-card'; diff --git a/src/entities/ray/ui/preview-card/index.ts b/src/entities/ray/ui/preview-card/index.ts new file mode 100644 index 00000000..6c61edcd --- /dev/null +++ b/src/entities/ray/ui/preview-card/index.ts @@ -0,0 +1 @@ +export { default as PreviewCard } from './preview-card.vue' diff --git a/src/entities/ray/ui/preview-card/preview-card.stories.ts b/src/entities/ray/ui/preview-card/preview-card.stories.ts new file mode 100644 index 00000000..468e6d4a --- /dev/null +++ b/src/entities/ray/ui/preview-card/preview-card.stories.ts @@ -0,0 +1,121 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { + rayCallerMock, + rayCarbonMock, + rayColorMock, + rayCounterMock, + rayDumpMock, + rayExceptionMock, + rayEmptyStringMock, + rayHideMock, + rayImageMock, + rayIntegerMock, + rayJsonMock, + rayLabelMock, + rayMeasureStartMock, + rayNotifyMock, + raySizeMock, + rayTableMock, + rayTextMock, + rayTraceMock, + rayLockMock, +} from '../../mocks'; +import { + rayLaravelEloquentMock, rayLaravelEventsMock, rayLaravelJobsMock, + rayLaravelQueryMock, + rayLaravelQueryNoBindingsMock, rayLaravelViewsMock +} from "../../mocks-laravel"; +import PreviewCard from './preview-card.vue'; + +const { normalizeRayEvent } = useRay() + +export default { + title: "Entities/ray/PreviewCard", + component: PreviewCard +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Text = Template.bind({}); +Text.args = {event: normalizeRayEvent(rayTextMock),}; + +export const EmptyText = Template.bind({}); +EmptyText.args = {event: normalizeRayEvent(rayEmptyStringMock),}; + +export const Trace = Template.bind({}); +Trace.args = {event: normalizeRayEvent(rayTraceMock),}; + +export const Table = Template.bind({}); +Table.args = {event: normalizeRayEvent(rayTableMock),}; + +export const Size = Template.bind({}); +Size.args = {event: normalizeRayEvent(raySizeMock),}; + +export const Notify = Template.bind({}); +Notify.args = {event: normalizeRayEvent(rayNotifyMock),}; + +export const Measure = Template.bind({}); +Measure.args = {event: normalizeRayEvent(rayMeasureStartMock),}; + +export const Label = Template.bind({}); +Label.args = {event: normalizeRayEvent(rayLabelMock),}; + +export const Json = Template.bind({}); +Json.args = {event: normalizeRayEvent(rayJsonMock),}; + +export const Image = Template.bind({}); +Image.args = {event: normalizeRayEvent(rayImageMock),}; + +export const Hide = Template.bind({}); +Hide.args = {event: normalizeRayEvent(rayHideMock),}; + +export const Exception = Template.bind({}); +Exception.args = {event: normalizeRayEvent(rayExceptionMock),}; + +export const Dump = Template.bind({}); +Dump.args = {event: normalizeRayEvent(rayDumpMock),}; + +export const Counter = Template.bind({}); +Counter.args = {event: normalizeRayEvent(rayCounterMock),}; + +export const Color = Template.bind({}); +Color.args = {event: normalizeRayEvent(rayColorMock),}; + +export const Carbon = Template.bind({}); +Carbon.args = {event: normalizeRayEvent(rayCarbonMock),}; + +export const Int = Template.bind({}); +Int.args = {event: normalizeRayEvent(rayIntegerMock),}; + +export const Caller = Template.bind({}); +Caller.args = {event: normalizeRayEvent(rayCallerMock),}; + +export const Lock = Template.bind({}); +Lock.args = {event: normalizeRayEvent(rayLockMock),}; + +export const LaravelQuery = Template.bind({}); +LaravelQuery.args = {event: normalizeRayEvent(rayLaravelQueryMock),}; + +export const LaravelQuery2 = Template.bind({}); +LaravelQuery2.args = {event: normalizeRayEvent(rayLaravelQueryNoBindingsMock),}; + +export const LaravelEloquent = Template.bind({}); +LaravelEloquent.args = {event: normalizeRayEvent(rayLaravelEloquentMock),}; + +export const LaravelViews = Template.bind({}); +LaravelViews.args = {event: normalizeRayEvent(rayLaravelViewsMock),}; + +export const LaravelEvents = Template.bind({}); +LaravelEvents.args = {event: normalizeRayEvent(rayLaravelEventsMock),}; + +export const LaravelJobs = Template.bind({}); +LaravelJobs.args = {event: normalizeRayEvent(rayLaravelJobsMock),}; diff --git a/src/entities/ray/ui/preview-card/preview-card.vue b/src/entities/ray/ui/preview-card/preview-card.vue new file mode 100644 index 00000000..0027d082 --- /dev/null +++ b/src/entities/ray/ui/preview-card/preview-card.vue @@ -0,0 +1,174 @@ + + + diff --git a/src/entities/ray/ui/ray-carbone/index.ts b/src/entities/ray/ui/ray-carbone/index.ts new file mode 100644 index 00000000..3f62df3f --- /dev/null +++ b/src/entities/ray/ui/ray-carbone/index.ts @@ -0,0 +1 @@ +export { default as RayCarbone } from './ray-carbone.vue' diff --git a/src/entities/ray/ui/ray-carbone/ray-carbone.stories.ts b/src/entities/ray/ui/ray-carbone/ray-carbone.stories.ts new file mode 100644 index 00000000..e5dd3b2e --- /dev/null +++ b/src/entities/ray/ui/ray-carbone/ray-carbone.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayCarbonMock } from '../../mocks' +import { RayContentCarbone } from "../../types"; +import RayCarbon from './ray-carbone.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayCarbon", + component: RayCarbon +} as Meta; + +const Template: Story = (args) => ({ + components: { RayCarbon }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + carbone: normalizeRayEvent(rayCarbonMock).payload.payloads[0].content as RayContentCarbone, +}; diff --git a/src/entities/ray/ui/ray-carbone/ray-carbone.vue b/src/entities/ray/ui/ray-carbone/ray-carbone.vue new file mode 100644 index 00000000..f8434a0d --- /dev/null +++ b/src/entities/ray/ui/ray-carbone/ray-carbone.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/entities/ray/ui/ray-custom/index.ts b/src/entities/ray/ui/ray-custom/index.ts new file mode 100644 index 00000000..bc8cd8f0 --- /dev/null +++ b/src/entities/ray/ui/ray-custom/index.ts @@ -0,0 +1 @@ +export { default as RayCustom } from './ray-custom.vue'; diff --git a/src/entities/ray/ui/ray-custom/ray-custom.stories.ts b/src/entities/ray/ui/ray-custom/ray-custom.stories.ts new file mode 100644 index 00000000..2761cf98 --- /dev/null +++ b/src/entities/ray/ui/ray-custom/ray-custom.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayTextMock } from '../../mocks'; +import { RayContentCustom } from '../../types'; +import RayCustom from './ray-custom.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayCustom", + component: RayCustom +} as Meta; + +const Template: Story = (args) => ({ + components: { RayCustom }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + content: (normalizeRayEvent(rayTextMock).payload.payloads[0].content as RayContentCustom) +}; diff --git a/src/entities/ray/ui/ray-custom/ray-custom.vue b/src/entities/ray/ui/ray-custom/ray-custom.vue new file mode 100644 index 00000000..4bc1f1c9 --- /dev/null +++ b/src/entities/ray/ui/ray-custom/ray-custom.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/entities/ray/ui/ray-eloquent/index.ts b/src/entities/ray/ui/ray-eloquent/index.ts new file mode 100644 index 00000000..ebb481df --- /dev/null +++ b/src/entities/ray/ui/ray-eloquent/index.ts @@ -0,0 +1 @@ +export { default as RayEloquent } from './ray-eloquent.vue'; diff --git a/src/entities/ray/ui/ray-eloquent/ray-eloquent.stories.ts b/src/entities/ray/ui/ray-eloquent/ray-eloquent.stories.ts new file mode 100644 index 00000000..bbace202 --- /dev/null +++ b/src/entities/ray/ui/ray-eloquent/ray-eloquent.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelEloquentMock } from '../../mocks-laravel'; +import { RayContentEloquent } from '../../types'; +import RayEloquent from './ray-eloquent.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayEloquent", + component: RayEloquent +} as Meta; + +const Template: Story = (args) => ({ + components: { RayEloquent }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + content: (normalizeRayEvent(rayLaravelEloquentMock).payload.payloads[0].content as RayContentEloquent) +}; diff --git a/src/entities/ray/ui/ray-eloquent/ray-eloquent.vue b/src/entities/ray/ui/ray-eloquent/ray-eloquent.vue new file mode 100644 index 00000000..54e79eb3 --- /dev/null +++ b/src/entities/ray/ui/ray-eloquent/ray-eloquent.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/entities/ray/ui/ray-event/index.ts b/src/entities/ray/ui/ray-event/index.ts new file mode 100644 index 00000000..41667122 --- /dev/null +++ b/src/entities/ray/ui/ray-event/index.ts @@ -0,0 +1 @@ +export { default as RayEvent } from './ray-event.vue'; diff --git a/src/entities/ray/ui/ray-event/ray-event.stories.ts b/src/entities/ray/ui/ray-event/ray-event.stories.ts new file mode 100644 index 00000000..70b075e7 --- /dev/null +++ b/src/entities/ray/ui/ray-event/ray-event.stories.ts @@ -0,0 +1,28 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelEventsMock } from '../../mocks-laravel'; +import { RayContentEvent } from '../../types'; +import RayEvent from './ray-event.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayEvent", + component: RayEvent +} as Meta; + +const Template: Story = (args) => ({ + components: { RayEvent }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + content: (normalizeRayEvent(rayLaravelEventsMock).payload.payloads[0].content as RayContentEvent) +}; + diff --git a/src/entities/ray/ui/ray-event/ray-event.vue b/src/entities/ray/ui/ray-event/ray-event.vue new file mode 100644 index 00000000..98e0c086 --- /dev/null +++ b/src/entities/ray/ui/ray-event/ray-event.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/entities/ray/ui/ray-exception/index.ts b/src/entities/ray/ui/ray-exception/index.ts new file mode 100644 index 00000000..513a5e59 --- /dev/null +++ b/src/entities/ray/ui/ray-exception/index.ts @@ -0,0 +1 @@ +export { default as RayException } from './ray-exception.vue'; diff --git a/src/entities/ray/ui/ray-exception/ray-exception.stories.ts b/src/entities/ray/ui/ray-exception/ray-exception.stories.ts new file mode 100644 index 00000000..801be39e --- /dev/null +++ b/src/entities/ray/ui/ray-exception/ray-exception.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayExceptionMock } from '../../mocks'; +import { RayContentException } from "../../types"; +import RayException from './ray-exception.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayException", + component: RayException +} as Meta; + +const Template: Story = (args) => ({ + components: { RayException }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Exception = Template.bind({}); +Exception.args = { + exception: normalizeRayEvent(rayExceptionMock).payload.payloads[0].content as RayContentException, +}; diff --git a/src/entities/ray/ui/ray-exception/ray-exception.vue b/src/entities/ray/ui/ray-exception/ray-exception.vue new file mode 100644 index 00000000..af7b9854 --- /dev/null +++ b/src/entities/ray/ui/ray-exception/ray-exception.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/entities/ray/ui/ray-file/index.ts b/src/entities/ray/ui/ray-file/index.ts new file mode 100644 index 00000000..0c577d41 --- /dev/null +++ b/src/entities/ray/ui/ray-file/index.ts @@ -0,0 +1 @@ +export { default as RayFile } from './ray-file.vue'; diff --git a/src/entities/ray/ui/ray-file/ray-file.stories.ts b/src/entities/ray/ui/ray-file/ray-file.stories.ts new file mode 100644 index 00000000..2984dcaf --- /dev/null +++ b/src/entities/ray/ui/ray-file/ray-file.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayExceptionMock } from "../../mocks"; +import { RayContentException } from "../../types"; +import RayFile from "./ray-file.vue"; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayFile", + component: RayFile +} as Meta; + +const Template: Story = (args) => ({ + components: { RayFile }, + setup() { + return { + args, + }; + }, + template: `This is a row 1`, +}); + +export const FileDefault = Template.bind({}); +FileDefault.args = { + file: (normalizeRayEvent(rayExceptionMock).payload.payloads[0].content as RayContentException).frames[0] +}; diff --git a/src/entities/ray/ui/ray-file/ray-file.vue b/src/entities/ray/ui/ray-file/ray-file.vue new file mode 100644 index 00000000..7b737702 --- /dev/null +++ b/src/entities/ray/ui/ray-file/ray-file.vue @@ -0,0 +1,96 @@ + + + + diff --git a/src/entities/ray/ui/ray-frame/index.ts b/src/entities/ray/ui/ray-frame/index.ts new file mode 100644 index 00000000..f715bf6d --- /dev/null +++ b/src/entities/ray/ui/ray-frame/index.ts @@ -0,0 +1 @@ +export { default as RayFrame } from './ray-frame.vue'; diff --git a/src/entities/ray/ui/ray-frame/ray-frame.stories.ts b/src/entities/ray/ui/ray-frame/ray-frame.stories.ts new file mode 100644 index 00000000..5fb5805f --- /dev/null +++ b/src/entities/ray/ui/ray-frame/ray-frame.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayCallerMock } from '../../mocks'; +import { RayContentFrame } from '../../types'; +import RayFrame from './ray-frame.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayFrame", + component: RayFrame +} as Meta; + +const Template: Story = (args) => ({ + components: { RayFrame }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + frame: (normalizeRayEvent(rayCallerMock).payload.payloads[0].content as RayContentFrame).frame +}; diff --git a/src/entities/ray/ui/ray-frame/ray-frame.vue b/src/entities/ray/ui/ray-frame/ray-frame.vue new file mode 100644 index 00000000..8a75e2fd --- /dev/null +++ b/src/entities/ray/ui/ray-frame/ray-frame.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/entities/ray/ui/ray-job/index.ts b/src/entities/ray/ui/ray-job/index.ts new file mode 100644 index 00000000..851c0dac --- /dev/null +++ b/src/entities/ray/ui/ray-job/index.ts @@ -0,0 +1 @@ +export { default as RayJob } from './ray-job.vue'; diff --git a/src/entities/ray/ui/ray-job/ray-job.stories.ts b/src/entities/ray/ui/ray-job/ray-job.stories.ts new file mode 100644 index 00000000..98555262 --- /dev/null +++ b/src/entities/ray/ui/ray-job/ray-job.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelJobsMock } from '../../mocks-laravel'; +import { RayContentJob } from '../../types'; +import RayJob from './ray-job.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayJob", + component: RayJob +} as Meta; + +const Template: Story = (args) => ({ + components: { RayJob }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + content: (normalizeRayEvent(rayLaravelJobsMock).payload.payloads[0].content as RayContentJob) +}; diff --git a/src/entities/ray/ui/ray-job/ray-job.vue b/src/entities/ray/ui/ray-job/ray-job.vue new file mode 100644 index 00000000..cd390f72 --- /dev/null +++ b/src/entities/ray/ui/ray-job/ray-job.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/entities/ray/ui/ray-lock/index.ts b/src/entities/ray/ui/ray-lock/index.ts new file mode 100644 index 00000000..34473194 --- /dev/null +++ b/src/entities/ray/ui/ray-lock/index.ts @@ -0,0 +1 @@ +export { default as RayLock } from './ray-lock.vue'; diff --git a/src/entities/ray/ui/ray-lock/ray-lock.stories.ts b/src/entities/ray/ui/ray-lock/ray-lock.stories.ts new file mode 100644 index 00000000..419bd58c --- /dev/null +++ b/src/entities/ray/ui/ray-lock/ray-lock.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLockMock } from '../../mocks' +import { RayContentLock } from '../../types' +import RayLock from './ray-lock.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayLock", + component: RayLock +} as Meta; + +const Template: Story = (args) => ({ + components: { RayLock }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + name: (normalizeRayEvent(rayLockMock).payload.payloads[0].content as RayContentLock).name +}; diff --git a/src/entities/ray/ui/ray-lock/ray-lock.vue b/src/entities/ray/ui/ray-lock/ray-lock.vue new file mode 100644 index 00000000..36e92c4f --- /dev/null +++ b/src/entities/ray/ui/ray-lock/ray-lock.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/entities/ray/ui/ray-log/index.ts b/src/entities/ray/ui/ray-log/index.ts new file mode 100644 index 00000000..e34e36f2 --- /dev/null +++ b/src/entities/ray/ui/ray-log/index.ts @@ -0,0 +1 @@ +export { default as RayLog } from './ray-log.vue' diff --git a/src/entities/ray/ui/ray-log/ray-log.stories.ts b/src/entities/ray/ui/ray-log/ray-log.stories.ts new file mode 100644 index 00000000..bb327006 --- /dev/null +++ b/src/entities/ray/ui/ray-log/ray-log.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayColorMock } from '../../mocks' +import { RayContentLog } from '../../types' +import RayLog from './ray-log.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayLog", + component: RayLog +} as Meta; + +const Template: Story = (args) => ({ + components: { RayLog }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + log: (normalizeRayEvent(rayColorMock).payload.payloads[0].content as RayContentLog).values[0] +}; diff --git a/src/entities/ray/ui/ray-log/ray-log.vue b/src/entities/ray/ui/ray-log/ray-log.vue new file mode 100644 index 00000000..b5445e80 --- /dev/null +++ b/src/entities/ray/ui/ray-log/ray-log.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/entities/ray/ui/ray-mail/index.ts b/src/entities/ray/ui/ray-mail/index.ts new file mode 100644 index 00000000..57da2b83 --- /dev/null +++ b/src/entities/ray/ui/ray-mail/index.ts @@ -0,0 +1 @@ +export { default as RayMail } from './ray-mail.vue' diff --git a/src/entities/ray/ui/ray-mail/ray-mail.stories.ts b/src/entities/ray/ui/ray-mail/ray-mail.stories.ts new file mode 100644 index 00000000..6fbbdd0f --- /dev/null +++ b/src/entities/ray/ui/ray-mail/ray-mail.stories.ts @@ -0,0 +1,28 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelMailableMock } from '../../mocks-laravel' +import { RayContentMail } from "../../types"; +import RayMail from "./ray-mail.vue"; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayMail", + component: RayMail +} as Meta; + +const Template: Story = (args) => ({ + components: { RayMail}, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Mailable = Template.bind({}); +Mailable.args = { + content: normalizeRayEvent(rayLaravelMailableMock).payload.payloads[0].content as RayContentMail +}; + diff --git a/src/entities/ray/ui/ray-mail/ray-mail.vue b/src/entities/ray/ui/ray-mail/ray-mail.vue new file mode 100644 index 00000000..19b7b671 --- /dev/null +++ b/src/entities/ray/ui/ray-mail/ray-mail.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/entities/ray/ui/ray-measure/index.ts b/src/entities/ray/ui/ray-measure/index.ts new file mode 100644 index 00000000..94b4c476 --- /dev/null +++ b/src/entities/ray/ui/ray-measure/index.ts @@ -0,0 +1 @@ +export { default as RayMeasure } from './ray-measure.vue' diff --git a/src/entities/ray/ui/ray-measure/ray-measure.stories.ts b/src/entities/ray/ui/ray-measure/ray-measure.stories.ts new file mode 100644 index 00000000..151ac166 --- /dev/null +++ b/src/entities/ray/ui/ray-measure/ray-measure.stories.ts @@ -0,0 +1,32 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayMeasureMock, rayMeasureStartMock } from '../../mocks' +import { RayContentMeasure } from "../../types"; +import RayMeasure from './ray-measure.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayMeasure", + component: RayMeasure +} as Meta; + +const Template: Story = (args) => ({ + components: { RayMeasure }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + measure: normalizeRayEvent(rayMeasureMock).payload.payloads[0].content as RayContentMeasure +}; + +export const Start = Template.bind({}); +Start.args = { + measure: normalizeRayEvent(rayMeasureStartMock).payload.payloads[0].content as RayContentMeasure +}; diff --git a/src/entities/ray/ui/ray-measure/ray-measure.vue b/src/entities/ray/ui/ray-measure/ray-measure.vue new file mode 100644 index 00000000..e2cbd4fa --- /dev/null +++ b/src/entities/ray/ui/ray-measure/ray-measure.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/entities/ray/ui/ray-origin/index.ts b/src/entities/ray/ui/ray-origin/index.ts new file mode 100644 index 00000000..5024283d --- /dev/null +++ b/src/entities/ray/ui/ray-origin/index.ts @@ -0,0 +1 @@ +export { default as RayOrigin } from './ray-origin.vue'; diff --git a/src/entities/ray/ui/ray-origin/ray-origin.stories.ts b/src/entities/ray/ui/ray-origin/ray-origin.stories.ts new file mode 100644 index 00000000..83a7e302 --- /dev/null +++ b/src/entities/ray/ui/ray-origin/ray-origin.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayCallerMock } from '../../mocks'; +import { RayPayloadOrigin } from '../../types'; +import RayOrigin from './ray-origin.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayOrigin", + component: RayOrigin +} as Meta; + +const Template: Story = (args) => ({ + components: { RayOrigin }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + origin: (normalizeRayEvent(rayCallerMock).payload.payloads[0].origin as RayPayloadOrigin) +}; diff --git a/src/entities/ray/ui/ray-origin/ray-origin.vue b/src/entities/ray/ui/ray-origin/ray-origin.vue new file mode 100644 index 00000000..f5577d7a --- /dev/null +++ b/src/entities/ray/ui/ray-origin/ray-origin.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/entities/ray/ui/ray-query/index.ts b/src/entities/ray/ui/ray-query/index.ts new file mode 100644 index 00000000..31ba576b --- /dev/null +++ b/src/entities/ray/ui/ray-query/index.ts @@ -0,0 +1 @@ +export { default as RayQuery } from './ray-query.vue'; diff --git a/src/entities/ray/ui/ray-query/ray-query.stories.ts b/src/entities/ray/ui/ray-query/ray-query.stories.ts new file mode 100644 index 00000000..cdc5f977 --- /dev/null +++ b/src/entities/ray/ui/ray-query/ray-query.stories.ts @@ -0,0 +1,33 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelQueryMock, rayLaravelQueryNoBindingsMock } from '../../mocks-laravel'; +import { RayContentSQL } from '../../types'; +import RayQuery from './ray-query.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayQuery", + component: RayQuery +} as Meta; + +const Template: Story = (args) => ({ + components: { RayQuery }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + content: (normalizeRayEvent(rayLaravelQueryMock).payload.payloads[0].content as RayContentSQL) +}; + + +export const NoBindings = Template.bind({}); +NoBindings.args = { + content: (normalizeRayEvent(rayLaravelQueryNoBindingsMock).payload.payloads[0].content as RayContentSQL) +}; diff --git a/src/entities/ray/ui/ray-query/ray-query.vue b/src/entities/ray/ui/ray-query/ray-query.vue new file mode 100644 index 00000000..3f2b2202 --- /dev/null +++ b/src/entities/ray/ui/ray-query/ray-query.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/entities/ray/ui/ray-table/index.ts b/src/entities/ray/ui/ray-table/index.ts new file mode 100644 index 00000000..bfe1ebcf --- /dev/null +++ b/src/entities/ray/ui/ray-table/index.ts @@ -0,0 +1 @@ +export { default as RayTable } from './ray-table.vue'; diff --git a/src/entities/ray/ui/ray-table/ray-table.stories.ts b/src/entities/ray/ui/ray-table/ray-table.stories.ts new file mode 100644 index 00000000..19a338db --- /dev/null +++ b/src/entities/ray/ui/ray-table/ray-table.stories.ts @@ -0,0 +1,28 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayTableMock } from '../../mocks' +import { RayContentMeasure } from "../../types"; +import RayTable from './ray-table.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayTable", + component: RayTable +} as Meta; + +const Template: Story = (args) => ({ + components: { RayTable }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + table: normalizeRayEvent(rayTableMock).payload.payloads[0].content as RayContentMeasure +}; + diff --git a/src/entities/ray/ui/ray-table/ray-table.vue b/src/entities/ray/ui/ray-table/ray-table.vue new file mode 100644 index 00000000..52bec031 --- /dev/null +++ b/src/entities/ray/ui/ray-table/ray-table.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/src/entities/ray/ui/ray-trace/index.ts b/src/entities/ray/ui/ray-trace/index.ts new file mode 100644 index 00000000..086b9672 --- /dev/null +++ b/src/entities/ray/ui/ray-trace/index.ts @@ -0,0 +1 @@ +export { default as RayTrace } from './ray-trace.vue'; diff --git a/src/entities/ray/ui/ray-trace/ray-trace.stories.ts b/src/entities/ray/ui/ray-trace/ray-trace.stories.ts new file mode 100644 index 00000000..042ef7e0 --- /dev/null +++ b/src/entities/ray/ui/ray-trace/ray-trace.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayTraceMock } from '../../mocks'; +import { RayContentFrames } from '../../types'; +import RayTrace from './ray-trace.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayTrace", + component: RayTrace +} as Meta; + +const Template: Story = (args) => ({ + components: { RayTrace }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + frames: (normalizeRayEvent(rayTraceMock).payload.payloads[0].content as RayContentFrames).frames +}; diff --git a/src/entities/ray/ui/ray-trace/ray-trace.vue b/src/entities/ray/ui/ray-trace/ray-trace.vue new file mode 100644 index 00000000..7c704c02 --- /dev/null +++ b/src/entities/ray/ui/ray-trace/ray-trace.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/src/entities/ray/ui/ray-view/index.ts b/src/entities/ray/ui/ray-view/index.ts new file mode 100644 index 00000000..84080245 --- /dev/null +++ b/src/entities/ray/ui/ray-view/index.ts @@ -0,0 +1 @@ +export { default as RayView } from './ray-view.vue' diff --git a/src/entities/ray/ui/ray-view/ray-view.stories.ts b/src/entities/ray/ui/ray-view/ray-view.stories.ts new file mode 100644 index 00000000..01398de7 --- /dev/null +++ b/src/entities/ray/ui/ray-view/ray-view.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useRay } from "../../lib"; +import { rayLaravelViewsMock } from '../../mocks-laravel'; +import { RayContentView } from '../../types'; +import RayViews from './ray-view.vue'; + +const { normalizeRayEvent } = useRay(); + +export default { + title: "Entities/ray/RayView", + component: RayViews +} as Meta; + +const Template: Story = (args) => ({ + components: { RayViews }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + view: normalizeRayEvent(rayLaravelViewsMock).payload.payloads[0].content as RayContentView +}; diff --git a/src/entities/ray/ui/ray-view/ray-view.vue b/src/entities/ray/ui/ray-view/ray-view.vue new file mode 100644 index 00000000..7a021171 --- /dev/null +++ b/src/entities/ray/ui/ray-view/ray-view.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/entities/sentry/index.ts b/src/entities/sentry/index.ts new file mode 100644 index 00000000..03a8d531 --- /dev/null +++ b/src/entities/sentry/index.ts @@ -0,0 +1,2 @@ +export * from './lib'; +export * from './ui'; diff --git a/src/entities/sentry/lib/index.ts b/src/entities/sentry/lib/index.ts new file mode 100644 index 00000000..576054b8 --- /dev/null +++ b/src/entities/sentry/lib/index.ts @@ -0,0 +1,2 @@ +export * from "./use-sentry"; + diff --git a/src/entities/sentry/lib/normalize-sentry-event.ts b/src/entities/sentry/lib/normalize-sentry-event.ts new file mode 100644 index 00000000..f416416b --- /dev/null +++ b/src/entities/sentry/lib/normalize-sentry-event.ts @@ -0,0 +1,15 @@ +import { EVENT_TYPES, ServerEvent, NormalizedEvent } from "~/src/shared/types"; +import { Sentry } from "../types"; + +export const normalizeSentryEvent = (event: ServerEvent): NormalizedEvent => ({ + id: event.uuid, + type: EVENT_TYPES.SENTRY, + labels: [EVENT_TYPES.SENTRY, 'exception'], + origin: { + logger: event.payload.logger, + environment: event.payload.environment + }, + serverName: event.payload?.server_name || '', + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload +}) diff --git a/src/entities/sentry/lib/use-sentry.ts b/src/entities/sentry/lib/use-sentry.ts new file mode 100644 index 00000000..ebdae0e3 --- /dev/null +++ b/src/entities/sentry/lib/use-sentry.ts @@ -0,0 +1,11 @@ +import { ServerEvent, NormalizedEvent } from '~/src/shared/types'; +import { Sentry } from "../types"; +import { normalizeSentryEvent } from "./normalize-sentry-event"; + +type TUseSentry = () => { + normalizeSentryEvent: (event: ServerEvent) => NormalizedEvent +} + +export const useSentry: TUseSentry = () => ({ + normalizeSentryEvent +}) diff --git a/src/entities/sentry/mocks/index.ts b/src/entities/sentry/mocks/index.ts new file mode 100644 index 00000000..ec6689fe --- /dev/null +++ b/src/entities/sentry/mocks/index.ts @@ -0,0 +1,15 @@ +import sentryCommonMock from './sentry-common.json'; +import sentryMock from './sentry-event.json'; +import sentryJSEventMock from './sentry-js-event.json'; +import sentryJSMock from './sentry-js.json'; +import sentryLaravelMock from './sentry-laravel.json'; +import sentrySpiralMock from './sentry-spiral.json'; + +export { + sentryCommonMock, + sentryMock, + sentryJSMock, + sentryJSEventMock, + sentryLaravelMock, + sentrySpiralMock, +} diff --git a/mocks/sentry-common.json b/src/entities/sentry/mocks/sentry-common.json similarity index 100% rename from mocks/sentry-common.json rename to src/entities/sentry/mocks/sentry-common.json diff --git a/mocks/sentry-event.json b/src/entities/sentry/mocks/sentry-event.json similarity index 93% rename from mocks/sentry-event.json rename to src/entities/sentry/mocks/sentry-event.json index c7c3343f..42478ba5 100644 --- a/mocks/sentry-event.json +++ b/src/entities/sentry/mocks/sentry-event.json @@ -1,11 +1,10 @@ { - "id": "17d252f1-a602-4ab5-9a1f-837cf8ba9be6", + "uuid": "17d252f1-a602-4ab5-9a1f-837cf8ba9be6", "type": "sentry", - "labels": [ - "sentry.1" - ], + "labels": ["sentry.1"], "origin": null, - "serverName": "", + "server_name": "", + "project_id": null, "date": "2023-09-17T20:33:28.000Z", "payload": { "event_id": "16f48014895e405ab3f94dd18018d34d", @@ -192,9 +191,7 @@ "data": { "connectionName": "sqlite", "executionTimeMs": 0.28, - "bindings": [ - "migrations" - ] + "bindings": ["migrations"] } }, { @@ -218,9 +215,7 @@ "data": { "connectionName": "sqlite", "executionTimeMs": 0.22, - "bindings": [ - "migrations" - ] + "bindings": ["migrations"] } }, { @@ -292,10 +287,7 @@ "data": { "connectionName": "sqlite", "executionTimeMs": 8.53, - "bindings": [ - "2014_10_12_000000_create_users_table", - 1 - ] + "bindings": ["2014_10_12_000000_create_users_table", 1] } }, { @@ -331,10 +323,7 @@ "data": { "connectionName": "sqlite", "executionTimeMs": 8.56, - "bindings": [ - "2014_10_12_100000_create_password_resets_table", - 1 - ] + "bindings": ["2014_10_12_100000_create_password_resets_table", 1] } }, { @@ -370,10 +359,7 @@ "data": { "connectionName": "sqlite", "executionTimeMs": 8.2, - "bindings": [ - "2019_08_19_000000_create_failed_jobs_table", - 1 - ] + "bindings": ["2019_08_19_000000_create_failed_jobs_table", 1] } }, { @@ -614,57 +600,27 @@ "url": "http://127.0.0.1:8000/", "method": "POST", "headers": { - "host": [ - "127.0.0.1:8000" - ], - "connection": [ - "keep-alive" - ], - "content-length": [ - "25" - ], + "host": ["127.0.0.1:8000"], + "connection": ["keep-alive"], + "content-length": ["25"], "sec-ch-ua": [ "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"" ], - "sec-ch-ua-platform": [ - "\"Windows\"" - ], - "sec-ch-ua-mobile": [ - "?0" - ], + "sec-ch-ua-platform": ["\"Windows\""], + "sec-ch-ua-mobile": ["?0"], "user-agent": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" ], - "content-type": [ - "application/json" - ], - "accept": [ - "*/*" - ], - "origin": [ - "http://127.0.0.1:8000" - ], - "sec-fetch-site": [ - "same-origin" - ], - "sec-fetch-mode": [ - "cors" - ], - "sec-fetch-dest": [ - "empty" - ], - "referer": [ - "http://127.0.0.1:8000/" - ], - "accept-encoding": [ - "gzip, deflate, br" - ], - "accept-language": [ - "en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,ka;q=0.6" - ], - "cookie": [ - "[Filtered]" - ] + "content-type": ["application/json"], + "accept": ["*/*"], + "origin": ["http://127.0.0.1:8000"], + "sec-fetch-site": ["same-origin"], + "sec-fetch-mode": ["cors"], + "sec-fetch-dest": ["empty"], + "referer": ["http://127.0.0.1:8000/"], + "accept-encoding": ["gzip, deflate, br"], + "accept-language": ["en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,ka;q=0.6"], + "cookie": ["[Filtered]"] }, "data": { "action": "sentry:event" diff --git a/mocks/sentry-js-event.json b/src/entities/sentry/mocks/sentry-js-event.json similarity index 90% rename from mocks/sentry-js-event.json rename to src/entities/sentry/mocks/sentry-js-event.json index 213e3e58..54aab248 100644 --- a/mocks/sentry-js-event.json +++ b/src/entities/sentry/mocks/sentry-js-event.json @@ -1,9 +1,9 @@ { - "id": "79e27c1d-e610-4c82-9180-aa07b51d2295", + "uuid": "79e27c1d-e610-4c82-9180-aa07b51d2295", "type": "sentry", "labels": ["sentry.1"], "origin": null, - "serverName": "", + "server_name": "", "date": "2023-09-17T21:49:59.000Z", "payload": { "message": "Something went wrong", @@ -12,6 +12,7 @@ "platform": "javascript", "timestamp": 1694987399.84, "environment": "production", + "server_name": "ButschsterLpp", "sdk": { "integrations": [ "InboundFilters", @@ -50,5 +51,6 @@ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" } } - } + }, + "project_id": null } diff --git a/mocks/sentry-js.json b/src/entities/sentry/mocks/sentry-js.json similarity index 95% rename from mocks/sentry-js.json rename to src/entities/sentry/mocks/sentry-js.json index 474c07fa..9742abbe 100644 --- a/mocks/sentry-js.json +++ b/src/entities/sentry/mocks/sentry-js.json @@ -1,9 +1,10 @@ { - "id": "28482489-cbf9-4331-b4d8-90549009f777", + "uuid": "28482489-cbf9-4331-b4d8-90549009f777", "type": "sentry", "labels": ["sentry.1"], "origin": null, - "serverName": "", + "server_name": "", + "project_id": null, "date": "2023-09-17T21:51:25.000Z", "payload": { "exception": { diff --git a/mocks/sentry-laravel.json b/src/entities/sentry/mocks/sentry-laravel.json similarity index 100% rename from mocks/sentry-laravel.json rename to src/entities/sentry/mocks/sentry-laravel.json diff --git a/mocks/sentry-spiral.json b/src/entities/sentry/mocks/sentry-spiral.json similarity index 100% rename from mocks/sentry-spiral.json rename to src/entities/sentry/mocks/sentry-spiral.json diff --git a/src/entities/sentry/types.ts b/src/entities/sentry/types.ts new file mode 100644 index 00000000..80b53b9c --- /dev/null +++ b/src/entities/sentry/types.ts @@ -0,0 +1,51 @@ +import * as SentryTypes from '@sentry/types' + +export type SentryFrame = SentryTypes.StackFrame + +export type SentryException = Omit & { + mechanism?: Omit & { + data?: { + [key: string]: string | boolean | number + } + } +} +export type SentryContextRuntime = SentryTypes.Runtime + +export type SentryContextOS = SentryTypes.OsContext +export type SentryContextApp = SentryTypes.AppContext + +export type SentryDevice = Omit & { + orientation: SentryTypes.DeviceContext['orientation'] | string + language?: string + id?: string + timezone?: string + battery_temperature?: string + locale?: string +} + +type SentryLevel = SentryTypes.Breadcrumb['level'] | string + +export type SentryBreadcrumb = Omit & { + level?: SentryLevel +} + +export type SentryRequest = Omit & { + headers?: { + [key: string]: string | string[]; + } +} + +export interface Sentry extends Omit { + contexts?: Omit & { + runtime?: SentryTypes.Runtime; + device?: SentryDevice + }, + request?: SentryRequest, + exception?: { + values: SentryException[] + }, + breadcrumbs?: { + values: SentryBreadcrumb[] + }, + level?: SentryLevel +} diff --git a/src/entities/sentry/ui/index.ts b/src/entities/sentry/ui/index.ts new file mode 100644 index 00000000..5c183b80 --- /dev/null +++ b/src/entities/sentry/ui/index.ts @@ -0,0 +1,2 @@ +export * from './preview-card'; +export * from './sentry-exception'; diff --git a/src/entities/sentry/ui/preview-card/index.ts b/src/entities/sentry/ui/preview-card/index.ts new file mode 100644 index 00000000..cdc15345 --- /dev/null +++ b/src/entities/sentry/ui/preview-card/index.ts @@ -0,0 +1,3 @@ +import PreviewCard from './preview-card.vue' + +export { PreviewCard }; diff --git a/src/entities/sentry/ui/preview-card/preview-card.stories.ts b/src/entities/sentry/ui/preview-card/preview-card.stories.ts new file mode 100644 index 00000000..6333ee2b --- /dev/null +++ b/src/entities/sentry/ui/preview-card/preview-card.stories.ts @@ -0,0 +1,46 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "../../lib"; +import { sentryMock, sentryJSEventMock, sentryLaravelMock, sentrySpiralMock } from '../../mocks'; +import PreviewCard from './preview-card.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Entities/sentry/PreviewCard", + component: PreviewCard +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Spiral = Template.bind({}); + +Spiral.args = { + event: normalizeSentryEvent(sentrySpiralMock), +}; + +export const Laravel = Template.bind({}); + +Laravel.args = { + event: normalizeSentryEvent(sentryLaravelMock), +}; + +export const Event = Template.bind({}); + +Event.args = { + event: normalizeSentryEvent(sentryMock), +}; + +export const JSEvent = Template.bind({}); + +JSEvent.args = { + event: normalizeSentryEvent(sentryJSEventMock), +}; + diff --git a/src/entities/sentry/ui/preview-card/preview-card.vue b/src/entities/sentry/ui/preview-card/preview-card.vue new file mode 100644 index 00000000..4fca4c05 --- /dev/null +++ b/src/entities/sentry/ui/preview-card/preview-card.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/entities/sentry/ui/sentry-exception/index.ts b/src/entities/sentry/ui/sentry-exception/index.ts new file mode 100644 index 00000000..d847eaf0 --- /dev/null +++ b/src/entities/sentry/ui/sentry-exception/index.ts @@ -0,0 +1,3 @@ +import SentryException from './sentry-exception.vue' + +export { SentryException }; diff --git a/src/entities/sentry/ui/sentry-exception/sentry-exception-frame.stories.ts b/src/entities/sentry/ui/sentry-exception/sentry-exception-frame.stories.ts new file mode 100644 index 00000000..5d024da9 --- /dev/null +++ b/src/entities/sentry/ui/sentry-exception/sentry-exception-frame.stories.ts @@ -0,0 +1,28 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "../../lib"; +import { sentrySpiralMock } from '../../mocks'; +import SentryExceptionFrame from './sentry-exception-frame.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Entities/sentry/SentryExceptionFrame", + component: SentryExceptionFrame +} as Meta; + +const Template: Story = (args) => ({ + components: { SentryExceptionFrame }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Frame = Template.bind({}); + +Frame.args = { + isOpen: true, + frame: normalizeSentryEvent(sentrySpiralMock).payload?.exception?.values?.[0]?.stacktrace?.frames?.[1], +}; diff --git a/components/SentryExceptionFrame/SentryExceptionFrame.vue b/src/entities/sentry/ui/sentry-exception/sentry-exception-frame.vue similarity index 78% rename from components/SentryExceptionFrame/SentryExceptionFrame.vue rename to src/entities/sentry/ui/sentry-exception/sentry-exception-frame.vue index f0be8fab..9539618c 100644 --- a/components/SentryExceptionFrame/SentryExceptionFrame.vue +++ b/src/entities/sentry/ui/sentry-exception/sentry-exception-frame.vue @@ -1,3 +1,31 @@ + + - - \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\r\n\"Laravel\r\n\r\n
\r\n\r\n\r\n\r\n\r\n
\r\n

© 2023 Laravel. All rights reserved.

\r\n\r\n
\r\n
\r\n
\r\n\r\n", + "raw": "From: sender \r\nTo: nsmitham@olson.biz, thelma68@hotmail.com\r\nCc: cc@site.com\r\nReply-To: To name \r\nSubject: Est debitis nihil repellendus sit.\r\nMessage-ID: <3083a616dd72895a1ea59be834f50869@site.com>\r\nMIME-Version: 1.0\r\nDate: Wed, 08 Mar 2023 11:22:03 +0000\r\nContent-Type: multipart/alternative; boundary=a4iT8D1T\r\n\r\n--a4iT8D1T\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n[Laravel](https://buggregator.dev)\r\n\r\nThe body of your message.\r\n\r\nButt=\r\non Text:=20\r\n\r\nThanks,\r\nLaravel\r\n\r\n=C2=A9 2023 Laravel. All rights reser=\r\nved.\r\n\r\n--a4iT8D1T\r\nContent-Type: text/html; charset=utf-8\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n\r\n\r\n\r\nLaravel\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n=\r\n\r\n\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n=\r\n\r\n\r\n\r\n\r\n\r\n=\r\n\r\n\r\n\r\n\r\n
\r\n\r\n3D\"Laravel\r\n\r\n
\r\n

T=\r\nhe body of your message.

\r\n\r\n\r\n\r\n\r\n\r\n

Thanks,<=\r\nbr>\r\nLaravel

\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\r\n\r\n\r\n\r\n
\r\n\r\n\r\n\r\n\r\n
\r\nButton Text=\r\n\r\n
\r\n
\r\n
\r\n
\r\n<=\r\ntable class=3D\"footer\" align=3D\"center\" width=3D\"570\" cellpadding=3D\"0\" cel=\r\nlspacing=3D\"0\" role=3D\"presentation\" style=3D\"box-sizing: border-box; font-=\r\nfamily: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, A=\r\nrial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';=\r\n position: relative; -premailer-cellpadding: 0; -premailer-cellspacing: 0; =\r\n-premailer-width: 570px; margin: 0 auto; padding: 0; text-align: center; wi=\r\ndth: 570px;\">\r\n
\r\n

=C2=A9 2023 Laravel. All rights reserved.

\r\n\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n--a4iT8D1T--\r\n\r\n.\r\n", + "attachments": [] + }, + "timestamp": 1678274523, + "project_id": null +} diff --git a/mocks/smtp-welcome.json b/src/entities/smtp/mocks/smtp-welcome.json similarity index 100% rename from mocks/smtp-welcome.json rename to src/entities/smtp/mocks/smtp-welcome.json diff --git a/src/entities/smtp/types.ts b/src/entities/smtp/types.ts new file mode 100644 index 00000000..8f695532 --- /dev/null +++ b/src/entities/smtp/types.ts @@ -0,0 +1,19 @@ +import { Attachment } from '~/src/shared/types'; + +export interface SMTPUser { + name: string, + email: string, +} +export interface SMTP { + id: string, + from: SMTPUser[], + reply_to: SMTPUser[], + subject: string, + to: SMTPUser[], + cc: SMTPUser[], + bcc: SMTPUser[], + text: string, + html: string, + raw: string, + attachments?: Record | Attachment[] +} diff --git a/src/entities/smtp/ui/index.ts b/src/entities/smtp/ui/index.ts new file mode 100644 index 00000000..52b27d6b --- /dev/null +++ b/src/entities/smtp/ui/index.ts @@ -0,0 +1 @@ +export * from './preview-card'; diff --git a/src/entities/smtp/ui/preview-card/index.ts b/src/entities/smtp/ui/preview-card/index.ts new file mode 100644 index 00000000..7f59f151 --- /dev/null +++ b/src/entities/smtp/ui/preview-card/index.ts @@ -0,0 +1,3 @@ +import PreviewCard from './preview-card.vue'; + +export { PreviewCard }; diff --git a/src/entities/smtp/ui/preview-card/preview-card.stories.ts b/src/entities/smtp/ui/preview-card/preview-card.stories.ts new file mode 100644 index 00000000..72fa5fd7 --- /dev/null +++ b/src/entities/smtp/ui/preview-card/preview-card.stories.ts @@ -0,0 +1,33 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSmtp } from "../../lib"; +import { smtpOrderMock, smtpWelcomeMock } from '../../mocks'; +import PreviewCard from './preview-card.vue'; + +const { normalizeSmtpEvent } = useSmtp(); + +export default { + title: "Entities/SMTP/PreviewCard", + component: PreviewCard +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const OrderShipped = Template.bind({}); + +OrderShipped.args = { + event: normalizeSmtpEvent(smtpOrderMock), +}; + +export const Welcome = Template.bind({}); + +Welcome.args = { + event: normalizeSmtpEvent(smtpWelcomeMock), +}; diff --git a/components/SmtpPreview/SmtpPreview.vue b/src/entities/smtp/ui/preview-card/preview-card.vue similarity index 65% rename from components/SmtpPreview/SmtpPreview.vue rename to src/entities/smtp/ui/preview-card/preview-card.vue index 739682b9..3faa7ca9 100644 --- a/components/SmtpPreview/SmtpPreview.vue +++ b/src/entities/smtp/ui/preview-card/preview-card.vue @@ -1,3 +1,21 @@ + + - - diff --git a/src/features/lib/cytoscape/config.ts b/src/features/lib/cytoscape/config.ts new file mode 100644 index 00000000..94341d61 --- /dev/null +++ b/src/features/lib/cytoscape/config.ts @@ -0,0 +1,42 @@ +import { Stylesheet } from "cytoscape"; + +export const cytoscapeStyles: Stylesheet[] = [ + { + selector: "node", + style: { + "background-color": "data(color)", + content: "data(name)", + "text-valign": "center", + "text-outline-width": 0, + color: "data(textColor)", + shape: "round-rectangle", + "padding-top": "10px", + "padding-left": "10px", + "padding-right": "10px", + "padding-bottom": "10px", + "text-wrap": "wrap", + width: "label", + height: "label", + "border-width": "2px", + "border-color": "#000", + }, + }, + { + selector: "edge", + style: { + "line-color": "data(color)", + "background-color": "data(color)", + "text-outline-width": "2px", + width: 2, + height: "label", + "target-arrow-shape": "triangle", + "target-arrow-color": "data(color)", + content: "data(label)", + color: "#fff", + "curve-style": "bezier", + "taxi-direction": "downward", + "edge-distances": "node-position", + "control-point-distance": 5, + }, + }, +] diff --git a/src/features/lib/cytoscape/index.ts b/src/features/lib/cytoscape/index.ts new file mode 100644 index 00000000..61bff829 --- /dev/null +++ b/src/features/lib/cytoscape/index.ts @@ -0,0 +1 @@ +export * from './use-cytoscape'; diff --git a/src/features/lib/cytoscape/inicialize.ts b/src/features/lib/cytoscape/inicialize.ts new file mode 100644 index 00000000..2dcbcdcb --- /dev/null +++ b/src/features/lib/cytoscape/inicialize.ts @@ -0,0 +1,47 @@ +import cytoscape, { Core as Cytoscape, ElementsDefinition, EventObjectNode, NodeSingular, Stylesheet } from "cytoscape"; +import dagre, { DagreLayoutOptions } from "cytoscape-dagre"; +import { cytoscapeStyles } from "./config"; + +cytoscape.use(dagre); + +type TInitializeProps = { + elements: ElementsDefinition, + container: HTMLElement, + onNodeHover: (node?: NodeSingular, event?: MouseEvent) => void, +} + +type TInitialize = (data: TInitializeProps) => () => void; + +const initialize: TInitialize = ({ + elements, + container, + onNodeHover, +}) => { + const cy: Cytoscape = cytoscape({ + container, + wheelSensitivity: 0.4, + elements, + layout: { + name: "dagre", + nodeSep: 10, + edgeSep: 10, + rankSep: 80, + rankDir: "TB", + } as DagreLayoutOptions, + style: cytoscapeStyles as Stylesheet[], + }); + + cy.on("mouseover", "node", (event: EventObjectNode) => { + onNodeHover(event.target, event.originalEvent); + }); + + cy.on("mouseout", "node", () => { + onNodeHover(undefined, undefined); + }); + + return () => cy.destroy(); +} + +export { + initialize, +}; diff --git a/utils/calc-graph-data.ts b/src/features/lib/cytoscape/prepare-data.ts similarity index 59% rename from utils/calc-graph-data.ts rename to src/features/lib/cytoscape/prepare-data.ts index 6faee8a0..1e8056cf 100644 --- a/utils/calc-graph-data.ts +++ b/src/features/lib/cytoscape/prepare-data.ts @@ -1,84 +1,105 @@ -import {formatDuration, humanFileSize} from "~/utils/formats"; -import {GraphTypes, ProfilerEdge, ProfilerEdges, TGraphEdge, TGraphNode} from "~/config/types"; +import { ProfilerEdge, ProfilerEdges } from "~/src/entities/profiler/types"; +import { useFormats } from "~/src/shared/lib/formats"; +import { GraphTypes } from "~/src/shared/types"; +import { TEdge, TNode } from "./types"; -function getColorForCallCount(callCount): string { +const { formatDuration, formatFileSize } = useFormats(); + + +const getColorForCallCount = (callCount: number) => { if (callCount <= 1) { return '#fff'; // Sky Blue for 1 call - } else if (callCount <= 10) { + } + + if (callCount <= 10) { return '#7BC8F6'; // Lighter Sky Blue - } else if (callCount <= 25) { + } + if (callCount <= 25) { return '#4DA6FF'; // Light Blue - } else if (callCount <= 50) { + } + if (callCount <= 50) { return '#1A8FFF'; // Brighter Blue - } else if (callCount <= 75) { + } + if (callCount <= 75) { return '#007FFF'; // Azure Blue - } else if (callCount <= 100) { + } + if (callCount <= 100) { return '#0059B3'; // Royal Blue - } else if (callCount <= 250) { + } + if (callCount <= 250) { return '#FFD700'; // Golden - } else if (callCount <= 500) { + } + if (callCount <= 500) { return '#FFA500'; // Orange - } else if (callCount <= 750) { + } + if (callCount <= 750) { return '#FF8C00'; // Dark Orange - } else if (callCount <= 1000) { + } + if (callCount <= 1000) { return '#FF4500'; // OrangeRed - } else if (callCount <= 2500) { + } + if (callCount <= 2500) { return '#FF0000'; // Red } return '#8B0000'; // Dark Red for 1000 to 1750 calls } - -function getColorForPercentCount(percent): string { +const getColorForPercentCount = (percent: number) => { if (percent <= 10) { return '#FFFFFF'; // White - } else if (percent <= 20) { + } + if (percent <= 20) { return '#f19797'; // Lighter shade towards dark red - } else if (percent <= 30) { + } + if (percent <= 30) { return '#d93939'; // Light shade towards dark red - } else if (percent <= 40) { + } + if (percent <= 40) { return '#ad1e1e'; // Intermediate lighter shade towards dark red - } else if (percent <= 50) { + } + if (percent <= 50) { return '#982525'; // Intermediate shade towards dark red - } else if (percent <= 60) { + } + if (percent <= 60) { return '#862323'; // Intermediate darker shade towards dark red - } else if (percent <= 70) { + } + if (percent <= 70) { return '#671d1d'; // Darker shade towards dark red - } else if (percent <= 80) { + } + if (percent <= 80) { return '#540d0d'; // More towards dark red - } else if (percent <= 90) { + } + if (percent <= 90) { return '#340707'; // Almost dark red } return '#2d0606'; // Dark red } - -function invertHexColor(hex): string { +const invertHexColor = (hexInput: string) => { // If the first character is a hash, remove it for processing - hex = hex.replace('#', ''); + const hex = hexInput.replace('#', ''); // Convert hex to RGB - let r = parseInt(hex.substr(0, 2), 16); - let g = parseInt(hex.substr(2, 2), 16); - let b = parseInt(hex.substr(4, 2), 16); + const r = parseInt(hex.substr(0, 2), 16); + const g = parseInt(hex.substr(2, 2), 16); + const b = parseInt(hex.substr(4, 2), 16); // Calculate the YIQ ratio - let yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; + const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; // Return black for bright colors, white for dark colors return (yiq >= 128) ? '#000' : '#fff'; } - const formatValue = (value: number, metric: string): string | number => { - const metricFormatMap: Record string | number> = { - p_mu: (a: number): string => `${a}%`, - p_pmu: (a: number): string => `${a}%`, - p_cpu: (a: number): string => `${a}%`, - p_wt: (a: number): string => `${a}%`, - mu: humanFileSize, - d_mu: humanFileSize, - pmu: humanFileSize, - d_pmu: humanFileSize, + const metricFormatMap: Record string|number> = { + p_mu: (a: number) => `${a}%`, + p_pmu: (a: number) => `${a}%`, + p_cpu: (a: number) => `${a}%`, + p_wt: (a: number) => `${a}%`, + mu: formatFileSize, + d_mu: formatFileSize, + pmu: formatFileSize, + d_pmu: formatFileSize, cpu: formatDuration, d_cpu: formatDuration, wt: formatDuration, @@ -88,33 +109,33 @@ const formatValue = (value: number, metric: string): string | number => { return metricFormatMap[metric]?.(value) || value } -export const calcGraphData: ( +export const prepareData: ( edges: ProfilerEdges, metric: GraphTypes, threshold: number, - minPercent: number + percent: number ) => ({ - nodes: TGraphNode[], - edges: TGraphEdge[] + nodes: TNode[], + edges: TEdge[] }) = - (edges: ProfilerEdges, metric: GraphTypes, threshold: number = 1, minPercent: number = 10) => Object.values(edges) + (edges: ProfilerEdges, metric , threshold = 1, percent = 10) => Object.values(edges) .reduce((arr, edge: ProfilerEdge, index) => { - let nodeColor: string = '#fff'; - let nodeTextColor: string = '#000'; - let edgeColor: string = '#fff'; + let nodeColor = '#fff'; + let nodeTextColor = '#000'; + let edgeColor = '#fff'; let edgeLabel: string = edge.cost.ct > 1 ? `${edge.cost.ct}x` : ''; if (metric === GraphTypes.CALLS) { - const metricKey: string = `ct`; - const isImportantNode: boolean = edge.cost[metricKey] >= minPercent; + const metricKey = `ct`; + const isImportantNode: boolean = edge.cost[metricKey] >= percent; if (!isImportantNode) { return arr } nodeColor = getColorForCallCount(edge.cost[metricKey]); } else { - const metricKey: string = `p_${metric}`; - const isImportantNode: boolean = edge.cost[metricKey] >= minPercent; + const metricKey = `p_${metric}`; + const isImportantNode: boolean = edge.cost[metricKey] >= percent; if (!isImportantNode && edge.cost[metricKey] <= threshold) { return arr } @@ -128,6 +149,13 @@ export const calcGraphData: ( edgeLabel = `${formatValue(edge.cost[metricKey], metricKey)}${postfix}`; } + const metricKey = `p_${metric}`; + + const isImportantNode = edge.cost.p_pmu > 10; + + if (!isImportantNode && edge.cost[metricKey] <= threshold) { + return arr + } arr.nodes.push({ data: { @@ -155,6 +183,6 @@ export const calcGraphData: ( return arr }, { - nodes: [] as TGraphNode[], - edges: [] as TGraphEdge[] + nodes: [] as TNode[], + edges: [] as TEdge[] }); diff --git a/src/features/lib/cytoscape/types.ts b/src/features/lib/cytoscape/types.ts new file mode 100644 index 00000000..74e0e683 --- /dev/null +++ b/src/features/lib/cytoscape/types.ts @@ -0,0 +1,23 @@ + +import { ProfilerCost } from "~/src/entities/profiler/types"; + +export type TNode = { + data: { + id: string, + name: string, + cost?: ProfilerCost, + color?: string, + textColor?: string, + } +} + +export type TEdge = { + data: { + id?: string, + source: string, + target: string, + label?: string, + color?: string, + weight?: number, + } +} diff --git a/src/features/lib/cytoscape/use-cytoscape.ts b/src/features/lib/cytoscape/use-cytoscape.ts new file mode 100644 index 00000000..a9c87ada --- /dev/null +++ b/src/features/lib/cytoscape/use-cytoscape.ts @@ -0,0 +1,7 @@ +import { initialize } from "./inicialize"; +import { prepareData as buildData } from "./prepare-data"; + +export const useCytoscape = () => ({ + initialize, + buildData +}) diff --git a/src/features/lib/flame-chart/build.ts b/src/features/lib/flame-chart/build.ts new file mode 100644 index 00000000..09be9b45 --- /dev/null +++ b/src/features/lib/flame-chart/build.ts @@ -0,0 +1,62 @@ +import {FlameChartNode} from "flame-chart-js/dist/types"; +import { ProfilerCost, ProfilerEdge, ProfilerEdges } from "~/src/entities/profiler/types"; +import { GraphTypes } from "~/src/shared/types"; + +type FlameChartData = FlameChartNode & { + cost: ProfilerCost +} +export const build = (edges: ProfilerEdges, field: GraphTypes): FlameChartData => { + let walked = [] as ProfilerEdge['callee'][] + + const datum: Record = {} + + Object.values(edges).forEach((edge) => { + const parent = edge.caller + const target = edge.callee + + const duration = (edge.cost[String(field)] || 0) > 0 ? edge.cost[String(field)] / 1_000 : 0 + const start = 0 + + if (target && !datum[target]) { + datum[target] = { + name: target, + start, + duration, + cost: edge.cost, + children: [] + } + } + + if (parent && !datum[parent]) { + datum[parent] = { + name: parent, + start, + duration, + cost: edge.cost, + children: [] + } + } + + // NOTE: walked skips several targettions (recursion detected), should be fixed + if (!parent || walked.includes(target)) { + // console.log(node, target) + return + } + + if (datum[parent] && datum[parent].children) { + const parentChildren = datum[parent].children || [] + + const lastChild = parentChildren ? parentChildren[parentChildren.length - 1]: null + datum[target].start = lastChild ? lastChild.start + lastChild.duration : datum[target].start + } else { + datum[target].start += datum[parent].start + } + + datum[parent].children?.push(datum[target]) + walked.push(target) + }) + + walked = [] + + return datum['main()'] +} diff --git a/src/features/lib/flame-chart/index.ts b/src/features/lib/flame-chart/index.ts new file mode 100644 index 00000000..93781ea3 --- /dev/null +++ b/src/features/lib/flame-chart/index.ts @@ -0,0 +1 @@ +export * from './use-flame-chart'; diff --git a/src/features/lib/flame-chart/use-flame-chart.ts b/src/features/lib/flame-chart/use-flame-chart.ts new file mode 100644 index 00000000..acc027da --- /dev/null +++ b/src/features/lib/flame-chart/use-flame-chart.ts @@ -0,0 +1,6 @@ +import {build} from "./build"; + + +export const useFlameChart = () => ({ + build +}) diff --git a/src/screens/http-dump/index.ts b/src/screens/http-dump/index.ts new file mode 100644 index 00000000..ed584959 --- /dev/null +++ b/src/screens/http-dump/index.ts @@ -0,0 +1 @@ +export * from './ui' diff --git a/components/HttpDumpPage/HttpDumpPage.stories.ts b/src/screens/http-dump/ui/http-dump-page/http-dump-page.stories.ts similarity index 50% rename from components/HttpDumpPage/HttpDumpPage.stories.ts rename to src/screens/http-dump/ui/http-dump-page/http-dump-page.stories.ts index 4b33908b..ac8a24d9 100644 --- a/components/HttpDumpPage/HttpDumpPage.stories.ts +++ b/src/screens/http-dump/ui/http-dump-page/http-dump-page.stories.ts @@ -1,11 +1,12 @@ import { Meta, Story } from "@storybook/vue3"; -import { normalizeHttpDumpEvent } from "~/utils/normalize-event"; -import httpDumpEventMock from '~/mocks/http-dump.json' -import httpDumpPDFEventMock from '~/mocks/http-dump-with-pdf.json' -import HttpDumpPage from "~/components/HttpDumpPage/HttpDumpPage.vue"; +import { useHttpDump } from '~/src/entities/http-dump'; +import { httpDumpMock, httpDumpPdfMock } from '~/src/entities/http-dump/mocks'; +import HttpDumpPage from "./http-dump-page.vue"; + +const { normalizeHttpDumpEvent } = useHttpDump(); export default { - title: "HttpDump/Page/HttpDumpPage", + title: "Screens/http-dump/HttpDumpPage", component: HttpDumpPage } as Meta; @@ -23,10 +24,10 @@ export const Default = Template.bind({}); Default.args = { - event: normalizeHttpDumpEvent(httpDumpEventMock), + event: normalizeHttpDumpEvent(httpDumpMock), }; export const WithPdf = Template.bind({}); WithPdf.args = { - event: normalizeHttpDumpEvent(httpDumpPDFEventMock), + event: normalizeHttpDumpEvent(httpDumpPdfMock), }; diff --git a/components/HttpDumpPage/HttpDumpPage.vue b/src/screens/http-dump/ui/http-dump-page/http-dump-page.vue similarity index 51% rename from components/HttpDumpPage/HttpDumpPage.vue rename to src/screens/http-dump/ui/http-dump-page/http-dump-page.vue index 9f9cca42..8ecc99fe 100644 --- a/components/HttpDumpPage/HttpDumpPage.vue +++ b/src/screens/http-dump/ui/http-dump-page/http-dump-page.vue @@ -1,74 +1,118 @@ + + - - diff --git a/src/screens/inspector/ui/inspector-page/index.ts b/src/screens/inspector/ui/inspector-page/index.ts new file mode 100644 index 00000000..d4b76f7a --- /dev/null +++ b/src/screens/inspector/ui/inspector-page/index.ts @@ -0,0 +1 @@ +export { default as InspectorPage } from './inspector-page.vue'; diff --git a/components/InspectorPage/InspectorPage.stories.ts b/src/screens/inspector/ui/inspector-page/inspector-page.stories.ts similarity index 52% rename from components/InspectorPage/InspectorPage.stories.ts rename to src/screens/inspector/ui/inspector-page/inspector-page.stories.ts index 8826691a..0e9b7f63 100644 --- a/components/InspectorPage/InspectorPage.stories.ts +++ b/src/screens/inspector/ui/inspector-page/inspector-page.stories.ts @@ -1,10 +1,12 @@ import {Meta, Story} from "@storybook/vue3"; -import {normalizeInspectorEvent} from "~/utils/normalize-event"; -import inspectorEventMock from '~/mocks/inspector.json' -import InspectorPage from '~/components/InspectorPage/InspectorPage.vue'; +import { useInspector } from "~/src/entities/inspector"; +import { inspectorMock } from '~/src/entities/inspector/mocks' +import InspectorPage from './inspector-page.vue'; + +const { normalizeInspectorEvent } = useInspector(); export default { - title: "Inspector/Page/InspectorPage", + title: "Screens/inspector/InspectorPage", component: InspectorPage } as Meta; @@ -20,6 +22,7 @@ const Template: Story = (args) => ({ export const Default = Template.bind({}); + Default.args = { - event: normalizeInspectorEvent(inspectorEventMock), + event: normalizeInspectorEvent(inspectorMock), }; diff --git a/components/InspectorPage/InspectorPage.vue b/src/screens/inspector/ui/inspector-page/inspector-page.vue similarity index 57% rename from components/InspectorPage/InspectorPage.vue rename to src/screens/inspector/ui/inspector-page/inspector-page.vue index 16dd22a0..db977f2f 100644 --- a/components/InspectorPage/InspectorPage.vue +++ b/src/screens/inspector/ui/inspector-page/inspector-page.vue @@ -1,3 +1,25 @@ + + - - diff --git a/src/screens/profiler/ui/call-graph/index.ts b/src/screens/profiler/ui/call-graph/index.ts new file mode 100644 index 00000000..6e7ffca0 --- /dev/null +++ b/src/screens/profiler/ui/call-graph/index.ts @@ -0,0 +1 @@ +export { default as CallGraph } from "./call-graph.vue"; diff --git a/src/screens/profiler/ui/call-stack-row/call-stack-row.stories.ts b/src/screens/profiler/ui/call-stack-row/call-stack-row.stories.ts new file mode 100644 index 00000000..a7d812bf --- /dev/null +++ b/src/screens/profiler/ui/call-stack-row/call-stack-row.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useProfiler } from '~/src/entities/profiler'; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import CallStackRow from './call-stack-row.vue'; + +const { normalizeProfilerEvent } = useProfiler(); + +export default { + title: "Screens/profiler/CallStackRow", + component: CallStackRow +} as Meta; + +const Template: Story = (args) => ({ + components: { CallStackRow }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + edge: normalizeProfilerEvent(profilerMock).payload.edges.e5, +}; diff --git a/src/screens/profiler/ui/call-stack-row/call-stack-row.vue b/src/screens/profiler/ui/call-stack-row/call-stack-row.vue new file mode 100644 index 00000000..989dcb59 --- /dev/null +++ b/src/screens/profiler/ui/call-stack-row/call-stack-row.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/screens/profiler/ui/call-stack-row/index.ts b/src/screens/profiler/ui/call-stack-row/index.ts new file mode 100644 index 00000000..e741c182 --- /dev/null +++ b/src/screens/profiler/ui/call-stack-row/index.ts @@ -0,0 +1 @@ +export { default as CallStackRow } from "./call-stack-row.vue"; diff --git a/src/screens/profiler/ui/call-stack/call-stack.stories.ts b/src/screens/profiler/ui/call-stack/call-stack.stories.ts new file mode 100644 index 00000000..87597208 --- /dev/null +++ b/src/screens/profiler/ui/call-stack/call-stack.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useProfiler } from "~/src/entities/profiler"; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import CallStack from './call-stack.vue'; + +const { normalizeProfilerEvent } = useProfiler(); + +export default { + title: "Screens/profiler/CallStack", + component: CallStack +} as Meta; + +const Template: Story = (args) => ({ + components: { CallStack }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + payload: normalizeProfilerEvent(profilerMock).payload, +}; diff --git a/src/screens/profiler/ui/call-stack/call-stack.vue b/src/screens/profiler/ui/call-stack/call-stack.vue new file mode 100644 index 00000000..bd8e3939 --- /dev/null +++ b/src/screens/profiler/ui/call-stack/call-stack.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/src/screens/profiler/ui/call-stack/index.ts b/src/screens/profiler/ui/call-stack/index.ts new file mode 100644 index 00000000..bfd5621e --- /dev/null +++ b/src/screens/profiler/ui/call-stack/index.ts @@ -0,0 +1 @@ +export { default as CallStack } from "./call-stack.vue"; diff --git a/src/screens/profiler/ui/call-stat-board/call-stat-board.stories.ts b/src/screens/profiler/ui/call-stat-board/call-stat-board.stories.ts new file mode 100644 index 00000000..75357516 --- /dev/null +++ b/src/screens/profiler/ui/call-stat-board/call-stat-board.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useProfiler } from "~/src/entities/profiler"; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import CallStatBoard from './call-stat-board.vue'; + +const { normalizeProfilerEvent } = useProfiler(); + +export default { + title: "Screens/profiler/CallStatBoard", + component: CallStatBoard +} as Meta; + +const Template: Story = (args) => ({ + components: { CallStatBoard }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + edge: normalizeProfilerEvent(profilerMock).payload.edges.e5 +}; diff --git a/src/screens/profiler/ui/call-stat-board/call-stat-board.vue b/src/screens/profiler/ui/call-stat-board/call-stat-board.vue new file mode 100644 index 00000000..6fc2a716 --- /dev/null +++ b/src/screens/profiler/ui/call-stat-board/call-stat-board.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/screens/profiler/ui/call-stat-board/index.ts b/src/screens/profiler/ui/call-stat-board/index.ts new file mode 100644 index 00000000..cbd3bd8e --- /dev/null +++ b/src/screens/profiler/ui/call-stat-board/index.ts @@ -0,0 +1 @@ +export { default as CallStatBoard } from './call-stat-board.vue' diff --git a/src/screens/profiler/ui/flame-graph/flame-graph.stories.ts b/src/screens/profiler/ui/flame-graph/flame-graph.stories.ts new file mode 100644 index 00000000..f265d48a --- /dev/null +++ b/src/screens/profiler/ui/flame-graph/flame-graph.stories.ts @@ -0,0 +1,28 @@ +import {Meta, Story} from "@storybook/vue3"; +import { useProfiler } from "~/src/entities/profiler"; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import { Profiler } from "~/src/entities/profiler/types"; +import FlameGraph from './flame-graph.vue'; + +const { normalizeProfilerEvent } = useProfiler(); + +export default { + title: "Screens/profiler/FlameGraph", + component: FlameGraph +} as Meta; + +const Template: Story = (args) => ({ + components: {FlameGraph}, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + edges: (normalizeProfilerEvent(profilerMock).payload as Profiler).edges, +}; diff --git a/src/screens/profiler/ui/flame-graph/flame-graph.vue b/src/screens/profiler/ui/flame-graph/flame-graph.vue new file mode 100644 index 00000000..3442c1cd --- /dev/null +++ b/src/screens/profiler/ui/flame-graph/flame-graph.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/screens/profiler/ui/flame-graph/index.ts b/src/screens/profiler/ui/flame-graph/index.ts new file mode 100644 index 00000000..2c72f6fc --- /dev/null +++ b/src/screens/profiler/ui/flame-graph/index.ts @@ -0,0 +1 @@ +export { default as FlameGraph } from './flame-graph.vue'; diff --git a/src/screens/profiler/ui/index.ts b/src/screens/profiler/ui/index.ts new file mode 100644 index 00000000..ca1812d4 --- /dev/null +++ b/src/screens/profiler/ui/index.ts @@ -0,0 +1,6 @@ +export * from './call-stack-row' +export * from './call-stack' +export * from './call-graph' +export * from './call-stat-board' +export * from './profiler-page' +export * from './flame-graph' diff --git a/src/screens/profiler/ui/profiler-page/index.ts b/src/screens/profiler/ui/profiler-page/index.ts new file mode 100644 index 00000000..7afc0d83 --- /dev/null +++ b/src/screens/profiler/ui/profiler-page/index.ts @@ -0,0 +1 @@ +export { default as ProfilerPage } from './profiler-page.vue' diff --git a/components/ProfilerPage/ProfilerPage.stories.ts b/src/screens/profiler/ui/profiler-page/profiler-page.stories.ts similarity index 53% rename from components/ProfilerPage/ProfilerPage.stories.ts rename to src/screens/profiler/ui/profiler-page/profiler-page.stories.ts index 1a164e19..313bae7d 100644 --- a/components/ProfilerPage/ProfilerPage.stories.ts +++ b/src/screens/profiler/ui/profiler-page/profiler-page.stories.ts @@ -1,10 +1,12 @@ import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import ProfilerPage from '~/components/ProfilerPage/ProfilerPage.vue'; -import profilerEventMock from '~/mocks/profiler.json' +import { useProfiler } from "~/src/entities/profiler"; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import ProfilerPage from './profiler-page.vue'; + +const { normalizeProfilerEvent } = useProfiler(); export default { - title: "Profiler/Page/ProfilerPage", + title: "Screens/profiler/ProfilerPage", component: ProfilerPage } as Meta; @@ -21,5 +23,5 @@ const Template: Story = (args) => ({ export const Default = Template.bind({}); Default.args = { - event: normalizeProfilerEvent(profilerEventMock), + event: normalizeProfilerEvent(profilerMock), }; diff --git a/src/screens/profiler/ui/profiler-page/profiler-page.vue b/src/screens/profiler/ui/profiler-page/profiler-page.vue new file mode 100644 index 00000000..ad389325 --- /dev/null +++ b/src/screens/profiler/ui/profiler-page/profiler-page.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/screens/sentry/index.ts b/src/screens/sentry/index.ts new file mode 100644 index 00000000..ed584959 --- /dev/null +++ b/src/screens/sentry/index.ts @@ -0,0 +1 @@ +export * from './ui' diff --git a/src/screens/sentry/ui/index.ts b/src/screens/sentry/ui/index.ts new file mode 100644 index 00000000..0fdfff1b --- /dev/null +++ b/src/screens/sentry/ui/index.ts @@ -0,0 +1,6 @@ +export * from './sentry-page-tags' +export * from './sentry-page-request' +export * from './sentry-page-device' +export * from './sentry-page-breadcrumbs' +export * from './sentry-page-app' +export * from './sentry-page' diff --git a/src/screens/sentry/ui/sentry-page-app/index.ts b/src/screens/sentry/ui/sentry-page-app/index.ts new file mode 100644 index 00000000..bd5f3ca3 --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-app/index.ts @@ -0,0 +1,3 @@ +export { default as SentryPageApp } from './sentry-page-app.vue' + + diff --git a/src/screens/sentry/ui/sentry-page-app/sentry-page-app.stories.ts b/src/screens/sentry/ui/sentry-page-app/sentry-page-app.stories.ts new file mode 100644 index 00000000..c31d58cb --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-app/sentry-page-app.stories.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "~/src/entities/sentry"; +import { sentryCommonMock } from '~/src/entities/sentry/mocks'; +import SentryPageApp from './sentry-page-app.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Screens/sentry/SentryPageApp", + component: SentryPageApp +} as Meta; + +const Template: Story = (args) => ({ + components: { SentryPageApp }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + app: normalizeSentryEvent(sentryCommonMock).payload?.contexts?.app, +}; diff --git a/src/screens/sentry/ui/sentry-page-app/sentry-page-app.vue b/src/screens/sentry/ui/sentry-page-app/sentry-page-app.vue new file mode 100644 index 00000000..22e7e392 --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-app/sentry-page-app.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/screens/sentry/ui/sentry-page-breadcrumbs/index.ts b/src/screens/sentry/ui/sentry-page-breadcrumbs/index.ts new file mode 100644 index 00000000..5b83c14c --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-breadcrumbs/index.ts @@ -0,0 +1,3 @@ +import SentryPageBreadcrumbs from "./sentry-page-breadcrumbs.vue"; + +export { SentryPageBreadcrumbs }; diff --git a/src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.stories.ts b/src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.stories.ts new file mode 100644 index 00000000..e564b52f --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.stories.ts @@ -0,0 +1,33 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "~/src/entities/sentry"; +import { sentryLaravelMock, sentrySpiralMock } from '~/src/entities/sentry/mocks' +import SentryPageBreadcrumbs from './sentry-page-breadcrumbs.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Screens/sentry/SentryPageBreadcrumbs", + component: SentryPageBreadcrumbs +} as Meta; + +const Template: Story = (args) => ({ + components: { SentryPageBreadcrumbs }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Laravel = Template.bind({}); + +Laravel.args = { + breadcrumbs: normalizeSentryEvent(sentryLaravelMock).payload.breadcrumbs?.values, +}; + +export const Spiral = Template.bind({}); + +Spiral.args = { + breadcrumbs: normalizeSentryEvent(sentrySpiralMock).payload.breadcrumbs?.values, +}; diff --git a/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.vue b/src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.vue similarity index 80% rename from components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.vue rename to src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.vue index 55329e26..1de620c2 100644 --- a/components/SentryPageBreadcrumbs/SentryPageBreadcrumbs.vue +++ b/src/screens/sentry/ui/sentry-page-breadcrumbs/sentry-page-breadcrumbs.vue @@ -1,5 +1,22 @@ + + - - diff --git a/src/screens/sentry/ui/sentry-page-request/index.ts b/src/screens/sentry/ui/sentry-page-request/index.ts new file mode 100644 index 00000000..5dd5b69e --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-request/index.ts @@ -0,0 +1,3 @@ +import SentryPageRequest from './sentry-page-request.vue' + +export { SentryPageRequest } diff --git a/src/screens/sentry/ui/sentry-page-request/sentry-page-request.stories.ts b/src/screens/sentry/ui/sentry-page-request/sentry-page-request.stories.ts new file mode 100644 index 00000000..61c5737d --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-request/sentry-page-request.stories.ts @@ -0,0 +1,33 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "~/src/entities/sentry"; +import { sentryLaravelMock, sentrySpiralMock } from '~/src/entities/sentry/mocks'; +import SentryPageRequest from './sentry-page-request.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Screens/sentry/SentryPageRequest", + component: SentryPageRequest +} as Meta; + +const Template: Story = (args) => ({ + components: { SentryPageRequest }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Laravel = Template.bind({}); + +Laravel.args = { + request: normalizeSentryEvent(sentryLaravelMock).payload.request, +}; + +export const Spiral = Template.bind({}); + +Spiral.args = { + request: normalizeSentryEvent(sentrySpiralMock).payload.request, +}; diff --git a/src/screens/sentry/ui/sentry-page-request/sentry-page-request.vue b/src/screens/sentry/ui/sentry-page-request/sentry-page-request.vue new file mode 100644 index 00000000..8cd726fb --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-request/sentry-page-request.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/screens/sentry/ui/sentry-page-tags/index.ts b/src/screens/sentry/ui/sentry-page-tags/index.ts new file mode 100644 index 00000000..c5d5e832 --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-tags/index.ts @@ -0,0 +1,3 @@ +import SentryPageTags from './sentry-page-tags.vue' + +export { SentryPageTags } diff --git a/src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.stories.ts b/src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.stories.ts new file mode 100644 index 00000000..22515063 --- /dev/null +++ b/src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.stories.ts @@ -0,0 +1,33 @@ +import { Meta, Story } from "@storybook/vue3"; +import { useSentry } from "~/src/entities/sentry"; +import { sentryLaravelMock, sentrySpiralMock } from '~/src/entities/sentry/mocks'; +import SentryPageTags from './sentry-page-tags.vue'; + +const { normalizeSentryEvent } = useSentry(); + +export default { + title: "Screens/sentry/SentryPageTags", + component: SentryPageTags +} as Meta; + +const Template: Story = (args) => ({ + components: { SentryPageTags }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Laravel = Template.bind({}); + +Laravel.args = { + payload: normalizeSentryEvent(sentryLaravelMock).payload, +}; + +export const Spiral = Template.bind({}); + +Spiral.args = { + payload: normalizeSentryEvent(sentrySpiralMock).payload, +}; diff --git a/components/SentryPageTags/SentryPageTags.vue b/src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.vue similarity index 73% rename from components/SentryPageTags/SentryPageTags.vue rename to src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.vue index 1b3c2018..a433c03b 100644 --- a/components/SentryPageTags/SentryPageTags.vue +++ b/src/screens/sentry/ui/sentry-page-tags/sentry-page-tags.vue @@ -1,3 +1,33 @@ + + - - diff --git a/src/screens/smtp/index.ts b/src/screens/smtp/index.ts new file mode 100644 index 00000000..ed584959 --- /dev/null +++ b/src/screens/smtp/index.ts @@ -0,0 +1 @@ +export * from './ui' diff --git a/src/screens/smtp/ui/index.ts b/src/screens/smtp/ui/index.ts new file mode 100644 index 00000000..080bc9d7 --- /dev/null +++ b/src/screens/smtp/ui/index.ts @@ -0,0 +1,3 @@ +export * from './smtp-page-preview' +export * from './smtp-page-addresses' +export * from './smtp-page' diff --git a/src/screens/smtp/ui/smtp-page-addresses/index.ts b/src/screens/smtp/ui/smtp-page-addresses/index.ts new file mode 100644 index 00000000..3ae9deb0 --- /dev/null +++ b/src/screens/smtp/ui/smtp-page-addresses/index.ts @@ -0,0 +1 @@ +export { default as SmtpPageAddresses } from './smtp-page-addresses.vue' diff --git a/src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.stories.ts b/src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.stories.ts new file mode 100644 index 00000000..2ad6778e --- /dev/null +++ b/src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.stories.ts @@ -0,0 +1,36 @@ +import {Meta, Story} from "@storybook/vue3"; +import SmtpPageAddresses from './smtp-page-addresses.vue'; + +export default { + title: "Screens/smtp/SmtpPageAddresses", + component: SmtpPageAddresses +} as Meta; + +const Template: Story = (args) => ({ + components: {SmtpPageAddresses}, + setup() { + return { + args, + }; + }, + template: ` + `, +}); + +export const Default = Template.bind({}); + +Default.args = { + addresses: [ + { + name: 'John Doe', + email: 'john-doe@example.com', + }, + { + name: 'Jane Smith', + email: 'JaneSmith@example.com', + }, + { + email: 'saraConor@example.com', + } + ], +}; diff --git a/components/SmtpPageAddresses/SmtpPageAddresses.vue b/src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.vue similarity index 67% rename from components/SmtpPageAddresses/SmtpPageAddresses.vue rename to src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.vue index 050159ff..54f15afd 100644 --- a/components/SmtpPageAddresses/SmtpPageAddresses.vue +++ b/src/screens/smtp/ui/smtp-page-addresses/smtp-page-addresses.vue @@ -1,3 +1,13 @@ + + - - diff --git a/src/shared/constants/index.ts b/src/shared/constants/index.ts new file mode 100644 index 00000000..c4e34b27 --- /dev/null +++ b/src/shared/constants/index.ts @@ -0,0 +1 @@ +export * from "./pages"; diff --git a/src/shared/constants/pages.ts b/src/shared/constants/pages.ts new file mode 100644 index 00000000..f04c0496 --- /dev/null +++ b/src/shared/constants/pages.ts @@ -0,0 +1,13 @@ +import { EVENT_TYPES } from "../types"; + +export const PAGE_TYPES = { + VAR_DUMP: EVENT_TYPES.VAR_DUMP, + SMTP: EVENT_TYPES.SMTP, + SENTRY: EVENT_TYPES.SENTRY, + PROFILER: EVENT_TYPES.PROFILER, + MONOLOG: EVENT_TYPES.MONOLOG, + INSPECTOR: EVENT_TYPES.INSPECTOR, + HTTP_DUMP: EVENT_TYPES.HTTP_DUMP, + RAY_DUMP: EVENT_TYPES.RAY_DUMP, + ALL_EVENTS: "all-events", +} diff --git a/utils/formats.ts b/src/shared/lib/formats/format-duration.ts similarity index 55% rename from utils/formats.ts rename to src/shared/lib/formats/format-duration.ts index c6d9f814..c53e1bf1 100644 --- a/utils/formats.ts +++ b/src/shared/lib/formats/format-duration.ts @@ -26,26 +26,3 @@ export const formatDuration = (inputMs: number) => { ) .join(", "); }; - -export const humanFileSize = (inputBytes: number) => { - let bytes = inputBytes; - const thresh = 1024; - - if (Math.abs(bytes) < thresh) { - return `${bytes} B`; - } - - const units = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; - let u = -1; - const r = 10 ** 1; - - do { - bytes /= thresh; - u += 1; - } while ( - Math.round(Math.abs(bytes) * r) / r >= thresh && - u < units.length - 1 - ); - - return `${bytes.toFixed(1)} ${units[u]}`; -}; diff --git a/src/shared/lib/formats/format-file-size.ts b/src/shared/lib/formats/format-file-size.ts new file mode 100644 index 00000000..4ecaf243 --- /dev/null +++ b/src/shared/lib/formats/format-file-size.ts @@ -0,0 +1,23 @@ + +export const formatFileSize = (inputBytes: number) => { + let bytes = inputBytes; + const thresh = 1024; + + if (Math.abs(bytes) < thresh) { + return `${bytes} B`; + } + + const units = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; + let u = -1; + const r = 10 ** 1; + + do { + bytes /= thresh; + u += 1; + } while ( + Math.round(Math.abs(bytes) * r) / r >= thresh && + u < units.length - 1 + ); + + return `${bytes.toFixed(1)} ${units[u]}`; +}; diff --git a/src/shared/lib/formats/index.ts b/src/shared/lib/formats/index.ts new file mode 100644 index 00000000..f6cbc96a --- /dev/null +++ b/src/shared/lib/formats/index.ts @@ -0,0 +1 @@ +export * from './use-formats'; diff --git a/src/shared/lib/formats/use-formats.ts b/src/shared/lib/formats/use-formats.ts new file mode 100644 index 00000000..6d61c899 --- /dev/null +++ b/src/shared/lib/formats/use-formats.ts @@ -0,0 +1,7 @@ +import { formatDuration } from './format-duration' +import { formatFileSize } from './format-file-size' + +export const useFormats = () => ({ + formatDuration, + formatFileSize +}) diff --git a/utils/io/centrifuge.ts b/src/shared/lib/io/centrifuge.ts similarity index 100% rename from utils/io/centrifuge.ts rename to src/shared/lib/io/centrifuge.ts index 03f56305..7d212033 100644 --- a/utils/io/centrifuge.ts +++ b/src/shared/lib/io/centrifuge.ts @@ -1,6 +1,6 @@ import { Centrifuge } from "centrifuge"; -import { logger } from "./logger"; import { WS_URL } from "./constants"; +import { logger } from "./logger"; type TUseCentrifuge = () => { centrifuge: Centrifuge diff --git a/utils/io/constants.ts b/src/shared/lib/io/constants.ts similarity index 100% rename from utils/io/constants.ts rename to src/shared/lib/io/constants.ts diff --git a/utils/io/index.ts b/src/shared/lib/io/index.ts similarity index 73% rename from utils/io/index.ts rename to src/shared/lib/io/index.ts index 00411c6c..b7f0cfcc 100644 --- a/utils/io/index.ts +++ b/src/shared/lib/io/index.ts @@ -1,5 +1,5 @@ export * from './constants'; export * from './types'; -export * from './events-requests'; +export * from './use-events-requests'; export * from './logger'; export * from './centrifuge'; diff --git a/utils/io/logger.ts b/src/shared/lib/io/logger.ts similarity index 100% rename from utils/io/logger.ts rename to src/shared/lib/io/logger.ts diff --git a/utils/io/types.ts b/src/shared/lib/io/types.ts similarity index 72% rename from utils/io/types.ts rename to src/shared/lib/io/types.ts index efe02656..79d8ba2c 100644 --- a/utils/io/types.ts +++ b/src/shared/lib/io/types.ts @@ -1,5 +1,3 @@ -import { ServerEvent } from "~/config/types"; - export type LoggerParams = [string, unknown] export interface ApiConnection { diff --git a/utils/io/events-requests.ts b/src/shared/lib/io/use-events-requests.ts similarity index 86% rename from utils/io/events-requests.ts rename to src/shared/lib/io/use-events-requests.ts index 9901ce65..75dbe122 100644 --- a/utils/io/events-requests.ts +++ b/src/shared/lib/io/use-events-requests.ts @@ -1,4 +1,4 @@ -import { EventId, ServerEvent, TEventType } from "~/config/types"; +import { EventId, EventType , ServerEvent } from '../../types'; import { REST_API_URL } from "./constants"; type TUseEventsRequests = () => { @@ -6,7 +6,7 @@ type TUseEventsRequests = () => { getSingle: (id: EventId) => Promise | null>, deleteAll: () => Promise, deleteSingle: (id: EventId) => Promise, - deleteByType: (type: TEventType) => Promise, + deleteByType: (type: EventType) => Promise, getEventRestUrl: (param: EventId | undefined) => string } @@ -45,7 +45,7 @@ export const useEventsRequests: TUseEventsRequests = () => { console.error('Fetch Error', err) }) - const deleteByType = (type: TEventType) => fetch(getEventRestUrl(), { method: 'DELETE', body: JSON.stringify({type}) }) + const deleteByType = (type: EventType) => fetch(getEventRestUrl(), { method: 'DELETE', body: JSON.stringify({type}) }) .catch((err) => { console.error('Fetch Error', err) }) diff --git a/src/shared/lib/use-api-transport/index.ts b/src/shared/lib/use-api-transport/index.ts new file mode 100644 index 00000000..2278f183 --- /dev/null +++ b/src/shared/lib/use-api-transport/index.ts @@ -0,0 +1 @@ +export { useApiTransport } from './use-api-transport' diff --git a/utils/api-transport.ts b/src/shared/lib/use-api-transport/use-api-transport.ts similarity index 90% rename from utils/api-transport.ts rename to src/shared/lib/use-api-transport/use-api-transport.ts index 4166dad6..f244aee5 100644 --- a/utils/api-transport.ts +++ b/src/shared/lib/use-api-transport/use-api-transport.ts @@ -1,11 +1,10 @@ -import { EventId, TEventType } from "~/config/types"; -import { useEventsRequests } from "~/utils/io/events-requests"; -import { useEventStore } from "~/stores/events"; import { useConnectionStore } from "~/stores/connections"; -import { useCentrifuge } from "./io"; +import { useEventStore } from "~/stores/events"; +import { EventId, EventType } from '../../types'; +import { useCentrifuge, useEventsRequests } from "../io"; const CHECK_CONNECTION_INTERVAL = 10000 -export const apiTransport = () => { +export const useApiTransport = () => { const { centrifuge } = useCentrifuge() const eventsStore = useEventStore() const connectionStore = useConnectionStore() @@ -74,7 +73,7 @@ export const apiTransport = () => { return deleteAll(); } - const deleteEventsByType = (type: TEventType) => { + const deleteEventsByType = (type: EventType) => { if (getWSConnection()) { return centrifuge.rpc(`delete:api/events`, {type}) } diff --git a/src/shared/lib/use-events/index.ts b/src/shared/lib/use-events/index.ts new file mode 100644 index 00000000..c39ee039 --- /dev/null +++ b/src/shared/lib/use-events/index.ts @@ -0,0 +1,2 @@ +export * from "./use-events"; + diff --git a/src/shared/lib/use-events/normalize-unknown-event.ts b/src/shared/lib/use-events/normalize-unknown-event.ts new file mode 100644 index 00000000..1f47ff6d --- /dev/null +++ b/src/shared/lib/use-events/normalize-unknown-event.ts @@ -0,0 +1,11 @@ +import { ServerEvent, NormalizedEvent } from "../../types"; + +export const normalizeUnknownEvent = (event: ServerEvent): NormalizedEvent => ({ + id: event.uuid, + type: 'unknown', + labels: [event.type], + origin: null, + serverName: "", + date: event.timestamp ? new Date(event.timestamp * 1000) : null, + payload: event.payload +}) diff --git a/src/shared/lib/use-events/use-events.ts b/src/shared/lib/use-events/use-events.ts new file mode 100644 index 00000000..83185ea7 --- /dev/null +++ b/src/shared/lib/use-events/use-events.ts @@ -0,0 +1,10 @@ +import { ServerEvent, NormalizedEvent } from '../../types'; +import { normalizeUnknownEvent } from "./normalize-unknown-event"; + +type TUseEvents = () => { + normalizeUnknownEvent: (event: ServerEvent) => NormalizedEvent +} + +export const useEvents: TUseEvents = () => ({ + normalizeUnknownEvent +}) diff --git a/src/shared/lib/vendor/dumper.js b/src/shared/lib/vendor/dumper.js new file mode 100644 index 00000000..72effa25 --- /dev/null +++ b/src/shared/lib/vendor/dumper.js @@ -0,0 +1,538 @@ +export default function (doc) { + let refStyle = doc.createElement("style"), + rxEsc = /([.*+?^${}()|\[\]\/\\])/g, + idRx = /\bsf-dump-\d+-ref[012]\w+\b/, + keyHint = + 0 <= navigator.platform.toUpperCase().indexOf("MAC") ? "Cmd" : "Ctrl", + addEventListener = function (e, n, cb) { + e.addEventListener(n, cb, false); + }; + refStyle.innerHTML = + "pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }"; + ( + doc.documentElement.firstElementChild || doc.documentElement.children[0] + ).appendChild(refStyle); + refStyle = doc.createElement("style"); + ( + doc.documentElement.firstElementChild || doc.documentElement.children[0] + ).appendChild(refStyle); + if (!doc.addEventListener) { + addEventListener = function (element, eventName, callback) { + element.attachEvent("on" + eventName, function (e) { + e.preventDefault = function () { + e.returnValue = false; + }; + e.target = e.srcElement; + callback(e); + }); + }; + } + + function toggle(a, recursive) { + var s = a.nextSibling || {}, + oldClass = s.className, + arrow, + newClass; + if (/\bsf-dump-compact\b/.test(oldClass)) { + arrow = "▼"; + newClass = "sf-dump-expanded"; + } else if (/\bsf-dump-expanded\b/.test(oldClass)) { + arrow = "▶"; + newClass = "sf-dump-compact"; + } else { + return false; + } + if (doc.createEvent && s.dispatchEvent) { + var event = doc.createEvent("Event"); + event.initEvent( + "sf-dump-expanded" === newClass + ? "sfbeforedumpexpand" + : "sfbeforedumpcollapse", + true, + false + ); + s.dispatchEvent(event); + } + a.lastChild.innerHTML = arrow; + s.className = s.className.replace( + /\bsf-dump-(compact|expanded)\b/, + newClass + ); + if (recursive) { + try { + a = s.querySelectorAll("." + oldClass); + for (s = 0; s < a.length; ++s) { + if (-1 == a[s].className.indexOf(newClass)) { + a[s].className = newClass; + a[s].previousSibling.lastChild.innerHTML = arrow; + } + } + } catch (e) {} + } + return true; + } + + function collapse(a, recursive) { + var s = a.nextSibling || {}, + oldClass = s.className; + if (/\bsf-dump-expanded\b/.test(oldClass)) { + toggle(a, recursive); + return true; + } + return false; + } + + function expand(a, recursive) { + var s = a.nextSibling || {}, + oldClass = s.className; + if (/\bsf-dump-compact\b/.test(oldClass)) { + toggle(a, recursive); + return true; + } + return false; + } + + function collapseAll(root) { + var a = root.querySelector("a.sf-dump-toggle"); + if (a) { + collapse(a, true); + expand(a); + return true; + } + return false; + } + + function reveal(node) { + var previous, + parents = []; + while ( + (node = node.parentNode || {}) && + (previous = node.previousSibling) && + "A" === previous.tagName + ) { + parents.push(previous); + } + if (0 !== parents.length) { + parents.forEach(function (parent) { + expand(parent); + }); + return true; + } + return false; + } + + function highlight(root, activeNode, nodes) { + resetHighlightedNodes(root); + Array.from(nodes || []).forEach(function (node) { + if (!/\bsf-dump-highlight\b/.test(node.className)) { + node.className = node.className + " sf-dump-highlight"; + } + }); + if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { + activeNode.className = activeNode.className + " sf-dump-highlight-active"; + } + } + + function resetHighlightedNodes(root) { + Array.from( + root.querySelectorAll( + ".sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private" + ) + ).forEach(function (strNode) { + strNode.className = strNode.className.replace( + /\bsf-dump-highlight\b/, + "" + ); + strNode.className = strNode.className.replace( + /\bsf-dump-highlight-active\b/, + "" + ); + }); + } + + return function (root, x) { + root = doc.getElementById(root); + var indentRx = new RegExp( + "^(" + + (root.getAttribute("data-indent-pad") || " ").replace(rxEsc, "\\$1") + + ")+", + "m" + ), + options = { maxDepth: 1, maxStringLength: 160, fileLinkFormat: false }, + elt = root.getElementsByTagName("A"), + len = elt.length, + i = 0, + s, + h, + t = []; + while (i < len) t.push(elt[i++]); + for (i in x) { + options[i] = x[i]; + } + + function a(e, f) { + addEventListener(root, e, function (e, n) { + if ("A" == e.target.tagName) { + f(e.target, e); + } else if ("A" == e.target.parentNode.tagName) { + f(e.target.parentNode, e); + } else { + n = /\bsf-dump-ellipsis\b/.test(e.target.className) + ? e.target.parentNode + : e.target; + if ((n = n.nextElementSibling) && "A" == n.tagName) { + if (!/\bsf-dump-toggle\b/.test(n.className)) { + n = n.nextElementSibling || n; + } + f(n, e, true); + } + } + }); + } + + function isCtrlKey(e) { + return e.ctrlKey || e.metaKey; + } + + function xpathString(str) { + var parts = str.match(/[^'"]+|['"]/g).map(function (part) { + if ("'" == part) { + return '"\'"'; + } + if ('"' == part) { + return "'\"'"; + } + return "'" + part + "'"; + }); + return "concat(" + parts.join(",") + ", '')"; + } + + function xpathHasClass(className) { + return ( + "contains(concat(' ', normalize-space(@class), ' '), ' " + + className + + " ')" + ); + } + + addEventListener(root, "mouseover", function (e) { + if ("" != refStyle.innerHTML) { + refStyle.innerHTML = ""; + } + }); + a("mouseover", function (a, e, c) { + if (c) { + e.target.style.cursor = "pointer"; + } else if ((a = idRx.exec(a.className))) { + try { + refStyle.innerHTML = + "pre.sf-dump ." + + a[0] + + "{background-color: #B729D9; color: #FFF !important; border-radius: 2px}"; + } catch (e) {} + } + }); + a("click", function (a, e, c) { + if (/\bsf-dump-toggle\b/.test(a.className)) { + e.preventDefault(); + if (!toggle(a, isCtrlKey(e))) { + var r = doc.getElementById(a.getAttribute("href").substr(1)), + s = r.previousSibling, + f = r.parentNode, + t = a.parentNode; + t.replaceChild(r, a); + f.replaceChild(a, s); + t.insertBefore(s, r); + f = f.firstChild.nodeValue.match(indentRx); + t = t.firstChild.nodeValue.match(indentRx); + if (f && t && f[0] !== t[0]) { + r.innerHTML = r.innerHTML.replace( + new RegExp("^" + f[0].replace(rxEsc, "\\$1"), "mg"), + t[0] + ); + } + if (/\bsf-dump-compact\b/.test(r.className)) { + toggle(s, isCtrlKey(e)); + } + } + if (c) { + } else if (doc.getSelection) { + try { + doc.getSelection().removeAllRanges(); + } catch (e) { + doc.getSelection().empty(); + } + } else { + doc.selection.empty(); + } + } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { + e.preventDefault(); + e = a.parentNode.parentNode; + e.className = e.className.replace( + /\bsf-dump-str-(expand|collapse)\b/, + a.parentNode.className + ); + } + }); + elt = root.getElementsByTagName("SAMP"); + len = elt.length; + i = 0; + while (i < len) t.push(elt[i++]); + len = t.length; + for (i = 0; i < len; ++i) { + elt = t[i]; + if ("SAMP" == elt.tagName) { + a = elt.previousSibling || {}; + if ("A" != a.tagName) { + a = doc.createElement("A"); + a.className = "sf-dump-ref"; + elt.parentNode.insertBefore(a, elt); + } else { + a.innerHTML += " "; + } + a.title = + (a.title ? a.title + "\n[" : "[") + + keyHint + + "+click] Expand all children"; + a.innerHTML += + elt.className == "sf-dump-compact" + ? "" + : ""; + a.className += " sf-dump-toggle"; + x = 1; + if ("sf-dump" != elt.parentNode.className) { + x += elt.parentNode.getAttribute("data-depth") / 1; + } + } else if ( + /\bsf-dump-ref\b/.test(elt.className) && + (a = elt.getAttribute("href")) + ) { + a = a.substr(1); + elt.className += " " + a; + if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { + a = a != elt.nextSibling.id && doc.getElementById(a); + try { + s = a.nextSibling; + elt.appendChild(a); + s.parentNode.insertBefore(a, s); + if (/^[@#]/.test(elt.innerHTML)) { + elt.innerHTML += " "; + } else { + elt.innerHTML = ""; + elt.className = "sf-dump-ref"; + } + elt.className += " sf-dump-toggle"; + } catch (e) { + if ("&" == elt.innerHTML.charAt(0)) { + elt.innerHTML = "…"; + elt.className = "sf-dump-ref"; + } + } + } + } + } + if (doc.evaluate && Array.from && root.children.length > 1) { + root.setAttribute("tabindex", 0); + var SearchState = function () { + this.nodes = []; + this.idx = 0; + }; + SearchState.prototype = { + next: function () { + if (this.isEmpty()) { + return this.current(); + } + this.idx = this.idx < this.nodes.length - 1 ? this.idx + 1 : 0; + return this.current(); + }, + previous: function () { + if (this.isEmpty()) { + return this.current(); + } + this.idx = this.idx > 0 ? this.idx - 1 : this.nodes.length - 1; + return this.current(); + }, + isEmpty: function () { + return 0 === this.count(); + }, + current: function () { + if (this.isEmpty()) { + return null; + } + return this.nodes[this.idx]; + }, + reset: function () { + this.nodes = []; + this.idx = 0; + }, + count: function () { + return this.nodes.length; + }, + }; + + function showCurrent(state) { + var currentNode = state.current(), + currentRect, + searchRect; + if (currentNode) { + reveal(currentNode); + highlight(root, currentNode, state.nodes); + if ("scrollIntoView" in currentNode) { + currentNode.scrollIntoView(true); + currentRect = currentNode.getBoundingClientRect(); + searchRect = search.getBoundingClientRect(); + if (currentRect.top < searchRect.top + searchRect.height) { + window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); + } + } + } + counter.textContent = + (state.isEmpty() ? 0 : state.idx + 1) + " of " + state.count(); + } + + var search = doc.createElement("div"); + search.className = "sf-dump-search-wrapper sf-dump-search-hidden"; + search.innerHTML = + ' 0 of 0 '; + root.insertBefore(search, root.firstChild); + var state = new SearchState(); + var searchInput = search.querySelector(".sf-dump-search-input"); + var counter = search.querySelector(".sf-dump-search-count"); + var searchInputTimer = 0; + var previousSearchQuery = ""; + addEventListener(searchInput, "keyup", function (e) { + const searchQuery = + e.target + .value; /* Don't perform anything if the pressed key didn't change the query */ + if (searchQuery === previousSearchQuery) { + return; + } + previousSearchQuery = searchQuery; + clearTimeout(searchInputTimer); + searchInputTimer = setTimeout(function () { + state.reset(); + collapseAll(root); + resetHighlightedNodes(root); + if ("" === searchQuery) { + counter.textContent = "0 of 0"; + return; + } + const classMatches = [ + "sf-dump-str", + "sf-dump-key", + "sf-dump-public", + "sf-dump-protected", + "sf-dump-private", + ] + .map(xpathHasClass) + .join(" or "); + const xpathResult = doc.evaluate( + ".//span[" + + classMatches + + "][contains(translate(child::text(), " + + xpathString(searchQuery.toUpperCase()) + + ", " + + xpathString(searchQuery.toLowerCase()) + + "), " + + xpathString(searchQuery.toLowerCase()) + + ")]", + root, + null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, + null + ); + + let node; + while ((node = xpathResult.iterateNext())) state.nodes.push(node); + showCurrent(state); + }, 400); + }); + Array.from( + search.querySelectorAll( + ".sf-dump-search-input-next, .sf-dump-search-input-previous" + ) + ).forEach(function (btn) { + addEventListener(btn, "click", function (e) { + e.preventDefault(); + -1 !== e.target.className.indexOf("next") + ? state.next() + : state.previous(); + searchInput.focus(); + collapseAll(root); + showCurrent(state); + }); + }); + addEventListener(root, "keydown", function (e) { + var isSearchActive = !/\bsf-dump-search-hidden\b/.test( + search.className + ); + if ( + (114 === e.keyCode && !isSearchActive) || + (isCtrlKey(e) && 70 === e.keyCode) + ) { + /* F3 or CMD/CTRL + F */ + if (70 === e.keyCode && document.activeElement === searchInput) { + /* * If CMD/CTRL + F is hit while having focus on search input, * the user probably meant to trigger browser search instead. * Let the browser execute its behavior: */ + return; + } + e.preventDefault(); + search.className = search.className.replace( + /\bsf-dump-search-hidden\b/, + "" + ); + searchInput.focus(); + } else if (isSearchActive) { + if (27 === e.keyCode) { + /* ESC key */ + search.className += " sf-dump-search-hidden"; + e.preventDefault(); + resetHighlightedNodes(root); + searchInput.value = ""; + } else if ( + (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */ || + 13 === e.keyCode /* Enter */ || + 114 === e.keyCode /* F3 */ + ) { + e.preventDefault(); + e.shiftKey ? state.previous() : state.next(); + collapseAll(root); + showCurrent(state); + } + } + }); + } + if (0 >= options.maxStringLength) { + return; + } + try { + elt = root.querySelectorAll(".sf-dump-str"); + len = elt.length; + i = 0; + t = []; + while (i < len) t.push(elt[i++]); + len = t.length; + for (i = 0; i < len; ++i) { + elt = t[i]; + s = elt.innerText || elt.textContent; + x = s.length - options.maxStringLength; + if (0 < x) { + h = elt.innerHTML; + elt[elt.innerText ? "innerText" : "textContent"] = s.substring( + 0, + options.maxStringLength + ); + elt.className += " sf-dump-str-collapse"; + elt.innerHTML = + "" + + h + + '' + + "" + + elt.innerHTML + + ''; + } + } + } catch (e) {} + }; +} diff --git a/src/shared/mocks/escaped-html-string.ts b/src/shared/mocks/escaped-html-string.ts new file mode 100644 index 00000000..6b59a2db --- /dev/null +++ b/src/shared/mocks/escaped-html-string.ts @@ -0,0 +1 @@ +export default `<?xml version="1.0"?>
<one>
  <two>
    <three>3</three>
  </two>
</one>` diff --git a/mocks/mail.ts b/src/shared/mocks/html-code.ts similarity index 99% rename from mocks/mail.ts rename to src/shared/mocks/html-code.ts index c7f99b70..d6b8153f 100644 --- a/mocks/mail.ts +++ b/src/shared/mocks/html-code.ts @@ -1,4 +1,4 @@ -export const HTML = ` +export default ` diff --git a/src/shared/mocks/index.ts b/src/shared/mocks/index.ts new file mode 100644 index 00000000..8f5d2d58 --- /dev/null +++ b/src/shared/mocks/index.ts @@ -0,0 +1,6 @@ +import HTMLEscapedString from './escaped-html-string'; +import HTMLCode from './html-code'; +import PHPCode from './php-code'; +import SFDumpCode from './sf-dump-code'; + +export { HTMLCode, PHPCode, SFDumpCode, HTMLEscapedString }; diff --git a/src/shared/mocks/php-code.ts b/src/shared/mocks/php-code.ts new file mode 100644 index 00000000..93927235 --- /dev/null +++ b/src/shared/mocks/php-code.ts @@ -0,0 +1,20 @@ +export default `use RoadRunner\\Centrifugo\\CentrifugoApiInterface; + +final class UserBanService +{ + public function __construct( + private readonly UserRepository $repository, + private readonly CentrifugoApiInterface $ws + ) {} + + public function handle(string $userUuid): void + { + $user = $this->repository->findByPK($userUuid); + + // Ban user... + + // Disconnect from webscoket server + $this->ws->disconnect($user->getId()); + } +} +` diff --git a/src/shared/mocks/sf-dump-code.ts b/src/shared/mocks/sf-dump-code.ts new file mode 100644 index 00000000..a7b3d5e8 --- /dev/null +++ b/src/shared/mocks/sf-dump-code.ts @@ -0,0 +1 @@ +export default "
Nyholm\\Psr7\\ServerRequest {#1545\n  -attributes: array:4 [\n    \"rr_parsed_body\" => false\n    \"route\" => Spiral\\Router\\Route {#1543\n      #uriHandler: Spiral\\Router\\UriHandler {#82\n        -pattern: \"[<action>.html]\"\n        -slugify: Cocur\\Slugify\\Slugify {#1380\n          #rules: array:833 [\n            \"°\" => \"0\"\n            \"¹\" => \"1\"\n            \"²\" => \"2\"\n            \"³\" => \"3\"\n            \"\" => \"4\"\n            \"\" => \"5\"\n            \"\" => \"6\"\n            \"\" => \"7\"\n            \"\" => \"8\"\n            \"\" => \"9\"\n            \"\" => \"0\"\n            \"\" => \"1\"\n            \"\" => \"2\"\n            \"\" => \"3\"\n            \"\" => \"4\"\n            \"\" => \"5\"\n            \"\" => \"6\"\n            \"\" => \"7\"\n            \"\" => \"8\"\n            \"\" => \"9\"\n            \"æ\" => \"ae\"\n            \"ǽ\" => \"ae\"\n            \"À\" => \"A\"\n            \"Á\" => \"A\"\n            \"Â\" => \"A\"\n            \"Ã\" => \"A\"\n            \"Å\" => \"AA\"\n            \"Ǻ\" => \"A\"\n            \"Ă\" => \"A\"\n            \"Ǎ\" => \"A\"\n            \"Æ\" => \"AE\"\n            \"Ǽ\" => \"AE\"\n            \"à\" => \"a\"\n            \"á\" => \"a\"\n            \"â\" => \"a\"\n            \"ã\" => \"a\"\n            \"å\" => \"aa\"\n            \"ǻ\" => \"a\"\n            \"ă\" => \"a\"\n            \"ǎ\" => \"a\"\n            \"ª\" => \"a\"\n            \"@\" => \"at\"\n            \"Ĉ\" => \"C\"\n            \"Ċ\" => \"C\"\n            \"Ç\" => \"C\"\n            \"ç\" => \"c\"\n            \"ĉ\" => \"c\"\n            \"ċ\" => \"c\"\n            \"©\" => \"c\"\n            \"Ð\" => \"Dj\"\n            \"Đ\" => \"D\"\n            \"ð\" => \"dj\"\n            \"đ\" => \"d\"\n            \"È\" => \"E\"\n            \"É\" => \"E\"\n            \"Ê\" => \"E\"\n            \"Ë\" => \"E\"\n            \"Ĕ\" => \"E\"\n            \"Ė\" => \"E\"\n            \"è\" => \"e\"\n            \"é\" => \"e\"\n            \"ê\" => \"e\"\n            \"ë\" => \"e\"\n            \"ĕ\" => \"e\"\n            \"ė\" => \"e\"\n            \"ƒ\" => \"f\"\n            \"Ĝ\" => \"G\"\n            \"Ġ\" => \"G\"\n            \"ĝ\" => \"g\"\n            \"ġ\" => \"g\"\n            \"Ĥ\" => \"H\"\n            \"Ħ\" => \"H\"\n            \"ĥ\" => \"h\"\n            \"ħ\" => \"h\"\n            \"Ì\" => \"I\"\n            \"Í\" => \"I\"\n            \"Î\" => \"I\"\n            \"Ï\" => \"I\"\n            \"Ĩ\" => \"I\"\n            \"Ĭ\" => \"I\"\n            \"Ǐ\" => \"I\"\n            \"Į\" => \"I\"\n            \"IJ\" => \"IJ\"\n            \"ì\" => \"i\"\n            \"í\" => \"i\"\n            \"î\" => \"i\"\n            \"ï\" => \"i\"\n            \"ĩ\" => \"i\"\n            \"ĭ\" => \"i\"\n            \"ǐ\" => \"i\"\n            \"į\" => \"i\"\n            \"ij\" => \"ij\"\n            \"Ĵ\" => \"J\"\n            \"ĵ\" => \"j\"\n            \"Ĺ\" => \"L\"\n            \"Ľ\" => \"L\"\n            \"Ŀ\" => \"L\"\n            \"ĺ\" => \"l\"\n            \"ľ\" => \"l\"\n            \"ŀ\" => \"l\"\n            \"Ñ\" => \"N\"\n            \"ñ\" => \"n\"\n            \"ʼn\" => \"n\"\n            \"Ò\" => \"O\"\n            \"Ó\" => \"O\"\n            \"Ô\" => \"O\"\n            \"Õ\" => \"O\"\n            \"Ō\" => \"O\"\n            \"Ŏ\" => \"O\"\n            \"Ǒ\" => \"O\"\n            \"Ő\" => \"O\"\n            \"Ơ\" => \"O\"\n            \"Ø\" => \"OE\"\n            \"Ǿ\" => \"O\"\n            \"Œ\" => \"OE\"\n            \"ò\" => \"o\"\n            \"ó\" => \"o\"\n            \"ô\" => \"o\"\n            \"õ\" => \"o\"\n            \"ō\" => \"o\"\n            \"ŏ\" => \"o\"\n            \"ǒ\" => \"o\"\n            \"ő\" => \"o\"\n            \"ơ\" => \"o\"\n            \"ø\" => \"oe\"\n            \"ǿ\" => \"o\"\n            \"º\" => \"o\"\n            \"œ\" => \"oe\"\n            \"Ŕ\" => \"R\"\n            \"Ŗ\" => \"R\"\n            \"ŕ\" => \"r\"\n            \"ŗ\" => \"r\"\n            \"Ŝ\" => \"S\"\n            \"Ș\" => \"S\"\n            \"ŝ\" => \"s\"\n            \"ș\" => \"s\"\n            \"ſ\" => \"s\"\n            \"Ţ\" => \"T\"\n            \"Ț\" => \"T\"\n            \"Ŧ\" => \"T\"\n            \"Þ\" => \"TH\"\n            \"ţ\" => \"t\"\n            \"ț\" => \"t\"\n            \"ŧ\" => \"t\"\n            \"þ\" => \"th\"\n            \"Ù\" => \"U\"\n            \"Ú\" => \"U\"\n            \"Û\" => \"U\"\n            \"Ü\" => \"UE\"\n            \"Ũ\" => \"U\"\n            \"Ŭ\" => \"U\"\n            \"Ű\" => \"U\"\n            \"Ų\" => \"U\"\n            \"Ư\" => \"U\"\n            \"Ǔ\" => \"U\"\n            \"Ǖ\" => \"U\"\n            \"Ǘ\" => \"U\"\n            \"Ǚ\" => \"U\"\n            \"Ǜ\" => \"U\"\n            \"ù\" => \"u\"\n            \"ú\" => \"u\"\n            \"û\" => \"u\"\n            \"ü\" => \"ue\"\n            \"ũ\" => \"u\"\n            \"ŭ\" => \"u\"\n            \"ű\" => \"u\"\n            \"ų\" => \"u\"\n            \"ư\" => \"u\"\n            \"ǔ\" => \"u\"\n            \"ǖ\" => \"u\"\n            \"ǘ\" => \"u\"\n            \"ǚ\" => \"u\"\n            \"ǜ\" => \"u\"\n            \"Ŵ\" => \"W\"\n            \"ŵ\" => \"w\"\n            \"Ý\" => \"Y\"\n            \"Ÿ\" => \"Y\"\n            \"Ŷ\" => \"Y\"\n            \"ý\" => \"y\"\n            \"ÿ\" => \"y\"\n            \"ŷ\" => \"y\"\n            \"Ա\" => \"A\"\n            \"Բ\" => \"B\"\n            \"Գ\" => \"G\"\n            \"Դ\" => \"D\"\n            \"Ե\" => \"E\"\n            \"Զ\" => \"Z\"\n            \"Է\" => \"E\"\n            \"Ը\" => \"Y\"\n            \"Թ\" => \"Th\"\n            \"Ժ\" => \"Zh\"\n            \"Ի\" => \"I\"\n            \"Լ\" => \"L\"\n            \"Խ\" => \"Kh\"\n            \"Ծ\" => \"Ts\"\n            \"Կ\" => \"K\"\n            \"Հ\" => \"H\"\n            \"Ձ\" => \"Dz\"\n            \"Ղ\" => \"Gh\"\n            \"Ճ\" => \"Tch\"\n            \"Մ\" => \"M\"\n            \"Յ\" => \"Y\"\n            \"Ն\" => \"N\"\n            \"Շ\" => \"Sh\"\n            \"Ո\" => \"Vo\"\n            \"Չ\" => \"Ch\"\n            \"Պ\" => \"P\"\n            \"Ջ\" => \"J\"\n            \"Ռ\" => \"R\"\n            \"Ս\" => \"S\"\n            \"Վ\" => \"V\"\n            \"Տ\" => \"T\"\n            \"Ր\" => \"R\"\n            \"Ց\" => \"C\"\n            \"Ւ\" => \"u\"\n            \"Փ\" => \"Ph\"\n            \"Ք\" => \"Q\"\n            \"և\" => \"ev\"\n            \"Օ\" => \"O\"\n            \"Ֆ\" => \"F\"\n            \"ա\" => \"a\"\n            \"բ\" => \"b\"\n            \"գ\" => \"g\"\n            \"դ\" => \"d\"\n            \"ե\" => \"e\"\n            \"զ\" => \"z\"\n            \"է\" => \"e\"\n            \"ը\" => \"y\"\n            \"թ\" => \"th\"\n            \"ժ\" => \"zh\"\n            \"ի\" => \"i\"\n            \"լ\" => \"l\"\n            \"խ\" => \"kh\"\n            \"ծ\" => \"ts\"\n            \"կ\" => \"k\"\n            \"հ\" => \"h\"\n            \"ձ\" => \"dz\"\n            \"ղ\" => \"gh\"\n            \"ճ\" => \"tch\"\n            \"մ\" => \"m\"\n            \"յ\" => \"y\"\n            \"ն\" => \"n\"\n            \"շ\" => \"sh\"\n            \"ո\" => \"vo\"\n            \"չ\" => \"ch\"\n            \"պ\" => \"p\"\n            \"ջ\" => \"j\"\n            \"ռ\" => \"r\"\n            \"ս\" => \"s\"\n            \"վ\" => \"v\"\n            \"տ\" => \"t\"\n            \"ր\" => \"r\"\n            \"ց\" => \"c\"\n            \"ւ\" => \"u\"\n            \"փ\" => \"ph\"\n            \"ք\" => \"q\"\n            \"օ\" => \"o\"\n            \"ֆ\" => \"f\"\n            \"Ə\" => \"E\"\n            \"Ğ\" => \"G\"\n            \"İ\" => \"I\"\n            \"Ş\" => \"S\"\n            \"Ö\" => \"OE\"\n            \"ə\" => \"e\"\n            \"ğ\" => \"g\"\n            \"ı\" => \"i\"\n            \"ş\" => \"s\"\n            \"ö\" => \"oe\"\n            \"က\" => \"k\"\n            \"\" => \"kh\"\n            \"\" => \"g\"\n            \"\" => \"ga\"\n            \"\" => \"ng\"\n            \"\" => \"s\"\n            \"\" => \"sa\"\n            \"\" => \"z\"\n            \"စျ\" => \"za\"\n            \"\" => \"ny\"\n            \"\" => \"t\"\n            \"\" => \"ta\"\n            \"\" => \"d\"\n            \"\" => \"da\"\n            \"\" => \"na\"\n            \"\" => \"t\"\n            \"\" => \"ta\"\n            \"\" => \"d\"\n            \"\" => \"da\"\n            \"\" => \"n\"\n            \"\" => \"p\"\n            \"\" => \"pa\"\n            \"\" => \"b\"\n            \"\" => \"ba\"\n            \"\" => \"m\"\n            \"\" => \"y\"\n            \"\" => \"ya\"\n            \"\" => \"l\"\n            \"\" => \"w\"\n            \"\" => \"th\"\n            \"\" => \"h\"\n            \"\" => \"la\"\n            \"\" => \"a\"\n            \"\" => \"y\"\n            \"\" => \"ya\"\n            \"\" => \"w\"\n            \"ြွ\" => \"yw\"\n            \"ျွ\" => \"ywa\"\n            \"\" => \"h\"\n            \"\" => \"e\"\n            \"\" => \"-e\"\n            \"\" => \"i\"\n            \"\" => \"-i\"\n            \"\" => \"u\"\n            \"\" => \"-u\"\n            \"\" => \"aw\"\n            \"သြော\" => \"aw\"\n            \"\" => \"aw\"\n            \"\" => \"ywae\"\n            \"\" => \"hnaik\"\n            \"\" => \"0\"\n            \"\" => \"1\"\n            \"\" => \"2\"\n            \"\" => \"3\"\n            \"\" => \"4\"\n            \"\" => \"5\"\n            \"\" => \"6\"\n            \"\" => \"7\"\n            \"\" => \"8\"\n            \"\" => \"9\"\n            \"\" => \"\"\n            \"\" => \"\"\n            \"\" => \"\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"i\"\n            \"\" => \"i\"\n            \"ို\" => \"o\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"ေါင်\" => \"aung\"\n            \"ော\" => \"aw\"\n            \"ော်\" => \"aw\"\n            \"ေါ\" => \"aw\"\n            \"ေါ်\" => \"aw\"\n            \"\" => \"at\"\n            \"က်\" => \"et\"\n            \"ိုက်\" => \"aik\"\n            \"ောက်\" => \"auk\"\n            \"င်\" => \"in\"\n            \"ိုင်\" => \"aing\"\n            \"ောင်\" => \"aung\"\n            \"စ်\" => \"it\"\n            \"ည်\" => \"i\"\n            \"တ်\" => \"at\"\n            \"ိတ်\" => \"eik\"\n            \"ုတ်\" => \"ok\"\n            \"ွတ်\" => \"ut\"\n            \"ေတ်\" => \"it\"\n            \"ဒ်\" => \"d\"\n            \"ိုဒ်\" => \"ok\"\n            \"ုဒ်\" => \"ait\"\n            \"န်\" => \"an\"\n            \"ာန်\" => \"an\"\n            \"ိန်\" => \"ein\"\n            \"ုန်\" => \"on\"\n            \"ွန်\" => \"un\"\n            \"ပ်\" => \"at\"\n            \"ိပ်\" => \"eik\"\n            \"ုပ်\" => \"ok\"\n            \"ွပ်\" => \"ut\"\n            \"န်ုပ်\" => \"nub\"\n            \"မ်\" => \"an\"\n            \"ိမ်\" => \"ein\"\n            \"ုမ်\" => \"on\"\n            \"ွမ်\" => \"un\"\n            \"ယ်\" => \"e\"\n            \"ိုလ်\" => \"ol\"\n            \"ဉ်\" => \"in\"\n            \"\" => \"an\"\n            \"ိံ\" => \"ein\"\n            \"ုံ\" => \"on\"\n            \"\" => \"a\"\n            \"\" => \"aa\"\n            \"\" => \"e\"\n            \"\" => \"ii\"\n            \"\" => \"ei\"\n            \"\" => \"ae\"\n            \"\" => \"ai\"\n            \"\" => \"i\"\n            \"\" => \"o\"\n            \"\" => \"oi\"\n            \"\" => \"oii\"\n            \"\" => \"uu\"\n            \"\" => \"ou\"\n            \"\" => \"u\"\n            \"\" => \"B\"\n            \"\" => \"Bha\"\n            \"\" => \"Ca\"\n            \"\" => \"Chha\"\n            \"\" => \"Da\"\n            \"\" => \"Dha\"\n            \"\" => \"Fa\"\n            \"फ़\" => \"Fi\"\n            \"\" => \"Ga\"\n            \"\" => \"Gha\"\n            \"ग़\" => \"Ghi\"\n            \"\" => \"Ha\"\n            \"\" => \"Ja\"\n            \"\" => \"Jha\"\n            \"\" => \"Ka\"\n            \"\" => \"Kha\"\n            \"ख़\" => \"Khi\"\n            \"\" => \"L\"\n            \"\" => \"Li\"\n            \"\" => \"Li\"\n            \"\" => \"Lii\"\n            \"\" => \"Lii\"\n            \"\" => \"Ma\"\n            \"\" => \"Na\"\n            \"\" => \"Na\"\n            \"\" => \"Nia\"\n            \"\" => \"Nae\"\n            \"\" => \"Ni\"\n            \"\" => \"oms\"\n            \"\" => \"Pa\"\n            \"क़\" => \"Qi\"\n            \"\" => \"Ra\"\n            \"\" => \"Ri\"\n            \"\" => \"Ri\"\n            \"\" => \"Ri\"\n            \"\" => \"Sa\"\n            \"\" => \"Sha\"\n            \"\" => \"Shha\"\n            \"\" => \"Ta\"\n            \"\" => \"Ta\"\n            \"\" => \"Tha\"\n            \"\" => \"Tha\"\n            \"\" => \"Tha\"\n            \"\" => \"Thha\"\n            \"ड़\" => \"ugDha\"\n            \"ढ़\" => \"ugDhha\"\n            \"\" => \"Va\"\n            \"\" => \"Ya\"\n            \"य़\" => \"Yi\"\n            \"ज़\" => \"Za\"\n            \"\" => \"a\"\n            \"\" => \"b\"\n            \"\" => \"g\"\n            \"\" => \"d\"\n            \"\" => \"e\"\n            \"\" => \"v\"\n            \"\" => \"z\"\n            \"\" => \"t\"\n            \"\" => \"i\"\n            \"\" => \"k\"\n            \"\" => \"l\"\n            \"\" => \"m\"\n            \"\" => \"n\"\n            \"\" => \"o\"\n            \"\" => \"p\"\n            \"\" => \"zh\"\n            \"\" => \"r\"\n            \"\" => \"s\"\n            \"\" => \"t\"\n            \"\" => \"u\"\n            \"\" => \"f\"\n            \"\" => \"k\"\n            \"\" => \"gh\"\n            \"\" => \"q\"\n            \"\" => \"sh\"\n            \"\" => \"ch\"\n            \"\" => \"ts\"\n            \"\" => \"dz\"\n            \"\" => \"ts\"\n            \"\" => \"ch\"\n            \"\" => \"kh\"\n            \"\" => \"j\"\n            \"\" => \"h\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"a\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"ế\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"e\"\n            \"\" => \"i\"\n            \"\" => \"i\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"o\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"u\"\n            \"\" => \"y\"\n            \"\" => \"y\"\n            \"\" => \"y\"\n            \"\" => \"y\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"A\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"E\"\n            \"\" => \"I\"\n            \"\" => \"I\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"O\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"U\"\n            \"\" => \"Y\"\n            \"\" => \"Y\"\n            \"\" => \"Y\"\n            \"\" => \"Y\"\n            \"Ґ\" => \"G\"\n            \"І\" => \"I\"\n            \"Ї\" => \"Ji\"\n            \"Є\" => \"Ye\"\n            \"ґ\" => \"g\"\n            \"і\" => \"i\"\n            \"ї\" => \"ji\"\n            \"є\" => \"ye\"\n            \"Ā\" => \"A\"\n            \"Ē\" => \"E\"\n            \"Ģ\" => \"G\"\n            \"Ī\" => \"I\"\n            \"Ķ\" => \"K\"\n            \"Ļ\" => \"L\"\n            \"Ņ\" => \"N\"\n            \"Ū\" => \"U\"\n            \"ā\" => \"a\"\n            \"ē\" => \"e\"\n            \"ģ\" => \"g\"\n            \"ī\" => \"i\"\n            \"ķ\" => \"k\"\n            \"ļ\" => \"l\"\n            \"ņ\" => \"n\"\n            \"ū\" => \"u\"\n            \"Ä\" => \"AE\"\n            \"ä\" => \"ae\"\n            \"ΑΥ\" => \"AU\"\n            \"Αυ\" => \"Au\"\n            \"ΟΥ\" => \"OU\"\n            \"Ου\" => \"Ou\"\n            \"ΕΥ\" => \"EU\"\n            \"Ευ\" => \"Eu\"\n            \"ΕΙ\" => \"I\"\n            \"Ει\" => \"I\"\n            \"ΟΙ\" => \"I\"\n            \"Οι\" => \"I\"\n            \"ΥΙ\" => \"I\"\n            \"Υι\" => \"I\"\n            \"ΑΎ\" => \"AU\"\n            \"Αύ\" => \"Au\"\n            \"ΟΎ\" => \"OU\"\n            \"Ού\" => \"Ou\"\n            \"ΕΎ\" => \"EU\"\n            \"Εύ\" => \"Eu\"\n            \"ΕΊ\" => \"I\"\n            \"Εί\" => \"I\"\n            \"ΟΊ\" => \"I\"\n            \"Οί\" => \"I\"\n            \"ΎΙ\" => \"I\"\n            \"Ύι\" => \"I\"\n            \"ΥΊ\" => \"I\"\n            \"Υί\" => \"I\"\n            \"αυ\" => \"au\"\n            \"ου\" => \"ou\"\n            \"ευ\" => \"eu\"\n            \"ει\" => \"i\"\n            \"οι\" => \"i\"\n            \"υι\" => \"i\"\n            \"αύ\" => \"au\"\n            \"ού\" => \"ou\"\n            \"εύ\" => \"eu\"\n            \"εί\" => \"i\"\n            \"οί\" => \"i\"\n            \"ύι\" => \"i\"\n            \"υί\" => \"i\"\n            \"Α\" => \"A\"\n            \"Β\" => \"V\"\n            \"Γ\" => \"G\"\n            \"Δ\" => \"D\"\n            \"Ε\" => \"E\"\n            \"Ζ\" => \"Z\"\n            \"Η\" => \"I\"\n            \"Θ\" => \"Th\"\n            \"Ι\" => \"I\"\n            \"Κ\" => \"K\"\n            \"Λ\" => \"L\"\n            \"Μ\" => \"M\"\n            \"Ν\" => \"N\"\n            \"Ξ\" => \"X\"\n            \"Ο\" => \"O\"\n            \"Π\" => \"P\"\n            \"Ρ\" => \"R\"\n            \"Σ\" => \"S\"\n            \"Τ\" => \"T\"\n            \"Υ\" => \"I\"\n            \"Φ\" => \"F\"\n            \"Χ\" => \"Ch\"\n            \"Ψ\" => \"Ps\"\n            \"Ω\" => \"O\"\n            \"Ά\" => \"A\"\n            \"Έ\" => \"E\"\n            \"Ή\" => \"I\"\n            \"Ί\" => \"I\"\n            \"Ό\" => \"O\"\n            \"Ύ\" => \"I\"\n            \"Ϊ\" => \"I\"\n            \"Ϋ\" => \"I\"\n            \"ϒ\" => \"I\"\n            \"α\" => \"a\"\n            \"β\" => \"v\"\n            \"γ\" => \"g\"\n            \"δ\" => \"d\"\n            \"ε\" => \"e\"\n            \"ζ\" => \"z\"\n            \"η\" => \"i\"\n            \"θ\" => \"th\"\n            \"ι\" => \"i\"\n            \"κ\" => \"k\"\n            \"λ\" => \"l\"\n            \"μ\" => \"m\"\n            \"ν\" => \"n\"\n            \"ξ\" => \"x\"\n            \"ο\" => \"o\"\n            \"π\" => \"p\"\n            \"ρ\" => \"r\"\n            \"ς\" => \"s\"\n            \"σ\" => \"s\"\n            \"τ\" => \"t\"\n            \"υ\" => \"i\"\n            \"φ\" => \"f\"\n            \"χ\" => \"ch\"\n            \"ψ\" => \"ps\"\n            \"ω\" => \"o\"\n            \"ά\" => \"a\"\n            \"έ\" => \"e\"\n            \"ή\" => \"i\"\n            \"ί\" => \"i\"\n            \"ό\" => \"o\"\n            \"ύ\" => \"i\"\n            \"ϊ\" => \"i\"\n            \"ϋ\" => \"i\"\n            \"ΰ\" => \"i\"\n            \"ώ\" => \"o\"\n            \"ϐ\" => \"v\"\n            \"ϑ\" => \"th\"\n            \"Č\" => \"C\"\n            \"Ď\" => \"D\"\n            \"Ě\" => \"E\"\n            \"Ň\" => \"N\"\n            \"Ř\" => \"R\"\n            \"Š\" => \"S\"\n            \"Ť\" => \"T\"\n            \"Ů\" => \"U\"\n            \"Ž\" => \"Z\"\n            \"č\" => \"c\"\n            \"ď\" => \"d\"\n            \"ě\" => \"e\"\n            \"ň\" => \"n\"\n            \"ř\" => \"r\"\n            \"š\" => \"s\"\n            \"ť\" => \"t\"\n            \"ů\" => \"u\"\n            \"ž\" => \"z\"\n            \"أ\" => \"a\"\n            \"ب\" => \"b\"\n            \"ت\" => \"t\"\n            \"ث\" => \"th\"\n            \"ج\" => \"g\"\n            \"ح\" => \"h\"\n            \"خ\" => \"kh\"\n            \"د\" => \"d\"\n            \"ذ\" => \"th\"\n            \"ر\" => \"r\"\n            \"ز\" => \"z\"\n            \"س\" => \"s\"\n            \"ش\" => \"sh\"\n            \"ص\" => \"s\"\n            \"ض\" => \"d\"\n            \"ط\" => \"t\"\n            \"ظ\" => \"th\"\n            \"ع\" => \"aa\"\n            \"غ\" => \"gh\"\n            \"ف\" => \"f\"\n            \"ق\" => \"k\"\n            \"ك\" => \"k\"\n            \"ل\" => \"l\"\n            \"م\" => \"m\"\n            \"ن\" => \"n\"\n            \"ه\" => \"h\"\n            \"و\" => \"o\"\n            \"ي\" => \"y\"\n            \"Ą\" => \"A\"\n            \"Ć\" => \"C\"\n            \"Ę\" => \"E\"\n            \"Ł\" => \"L\"\n            \"Ń\" => \"N\"\n            \"Ś\" => \"S\"\n            \"Ź\" => \"Z\"\n            \"Ż\" => \"Z\"\n            \"ą\" => \"a\"\n            \"ć\" => \"c\"\n            \"ę\" => \"e\"\n            \"ł\" => \"l\"\n            \"ń\" => \"n\"\n            \"ś\" => \"s\"\n            \"ź\" => \"z\"\n            \"ż\" => \"z\"\n            \"ß\" => \"ss\"\n            \"Ъ\" => \"\"\n            \"Ь\" => \"\"\n            \"А\" => \"A\"\n            \"Б\" => \"B\"\n            \"Ц\" => \"C\"\n            \"Ч\" => \"Ch\"\n            \"Д\" => \"D\"\n            \"Е\" => \"E\"\n            \"Ё\" => \"E\"\n            \"Э\" => \"E\"\n            \"Ф\" => \"F\"\n            \"Г\" => \"G\"\n            \"Х\" => \"H\"\n            \"И\" => \"I\"\n            \"Й\" => \"Y\"\n            \"Я\" => \"Ya\"\n            \"Ю\" => \"Yu\"\n            \"К\" => \"K\"\n            \"Л\" => \"L\"\n            \"М\" => \"M\"\n            \"Н\" => \"N\"\n            \"О\" => \"O\"\n            \"П\" => \"P\"\n            \"Р\" => \"R\"\n            \"С\" => \"S\"\n            \"Ш\" => \"Sh\"\n            \"Щ\" => \"Shch\"\n            \"Т\" => \"T\"\n            \"У\" => \"U\"\n            \"В\" => \"V\"\n            \"Ы\" => \"Y\"\n            \"З\" => \"Z\"\n            \"Ж\" => \"Zh\"\n            \"ъ\" => \"\"\n            \"ь\" => \"\"\n            \"а\" => \"a\"\n            \"б\" => \"b\"\n            \"ц\" => \"c\"\n            \"ч\" => \"ch\"\n            \"д\" => \"d\"\n            \"е\" => \"e\"\n            \"ё\" => \"e\"\n            \"э\" => \"e\"\n            \"ф\" => \"f\"\n            \"г\" => \"g\"\n            \"х\" => \"h\"\n            \"и\" => \"i\"\n            \"й\" => \"y\"\n            \"я\" => \"ya\"\n            \"ю\" => \"yu\"\n            \"к\" => \"k\"\n            \"л\" => \"l\"\n            \"м\" => \"m\"\n            \"н\" => \"n\"\n            \"о\" => \"o\"\n            \"п\" => \"p\"\n            \"р\" => \"r\"\n            \"с\" => \"s\"\n            \"ш\" => \"sh\"\n            \"щ\" => \"shch\"\n            \"т\" => \"t\"\n            \"у\" => \"u\"\n            \"в\" => \"v\"\n            \"ы\" => \"y\"\n            \"з\" => \"z\"\n            \"ж\" => \"zh\"\n          ]\n          #provider: Cocur\\Slugify\\RuleProvider\\DefaultRuleProvider {#1365\n            #rules: array:36 [\n              \"arabic\" => array:28 [\n                \"أ\" => \"a\"\n                \"ب\" => \"b\"\n                \"ت\" => \"t\"\n                \"ث\" => \"th\"\n                \"ج\" => \"g\"\n                \"ح\" => \"h\"\n                \"خ\" => \"kh\"\n                \"د\" => \"d\"\n                \"ذ\" => \"th\"\n                \"ر\" => \"r\"\n                \"ز\" => \"z\"\n                \"س\" => \"s\"\n                \"ش\" => \"sh\"\n                \"ص\" => \"s\"\n                \"ض\" => \"d\"\n                \"ط\" => \"t\"\n                \"ظ\" => \"th\"\n                \"ع\" => \"aa\"\n                \"غ\" => \"gh\"\n                \"ف\" => \"f\"\n                \"ق\" => \"k\"\n                \"ك\" => \"k\"\n                \"ل\" => \"l\"\n                \"م\" => \"m\"\n                \"ن\" => \"n\"\n                \"ه\" => \"h\"\n                \"و\" => \"o\"\n                \"ي\" => \"y\"\n              ]\n              \"armenian\" => array:77 [\n                \"Ա\" => \"A\"\n                \"Բ\" => \"B\"\n                \"Գ\" => \"G\"\n                \"Դ\" => \"D\"\n                \"Ե\" => \"E\"\n                \"Զ\" => \"Z\"\n                \"Է\" => \"E\"\n                \"Ը\" => \"Y\"\n                \"Թ\" => \"Th\"\n                \"Ժ\" => \"Zh\"\n                \"Ի\" => \"I\"\n                \"Լ\" => \"L\"\n                \"Խ\" => \"Kh\"\n                \"Ծ\" => \"Ts\"\n                \"Կ\" => \"K\"\n                \"Հ\" => \"H\"\n                \"Ձ\" => \"Dz\"\n                \"Ղ\" => \"Gh\"\n                \"Ճ\" => \"Tch\"\n                \"Մ\" => \"M\"\n                \"Յ\" => \"Y\"\n                \"Ն\" => \"N\"\n                \"Շ\" => \"Sh\"\n                \"Ո\" => \"Vo\"\n                \"Չ\" => \"Ch\"\n                \"Պ\" => \"P\"\n                \"Ջ\" => \"J\"\n                \"Ռ\" => \"R\"\n                \"Ս\" => \"S\"\n                \"Վ\" => \"V\"\n                \"Տ\" => \"T\"\n                \"Ր\" => \"R\"\n                \"Ց\" => \"C\"\n                \"Ւ\" => \"u\"\n                \"Փ\" => \"Ph\"\n                \"Ք\" => \"Q\"\n                \"և\" => \"ev\"\n                \"Օ\" => \"O\"\n                \"Ֆ\" => \"F\"\n                \"ա\" => \"a\"\n                \"բ\" => \"b\"\n                \"գ\" => \"g\"\n                \"դ\" => \"d\"\n                \"ե\" => \"e\"\n                \"զ\" => \"z\"\n                \"է\" => \"e\"\n                \"ը\" => \"y\"\n                \"թ\" => \"th\"\n                \"ժ\" => \"zh\"\n                \"ի\" => \"i\"\n                \"լ\" => \"l\"\n                \"խ\" => \"kh\"\n                \"ծ\" => \"ts\"\n                \"կ\" => \"k\"\n                \"հ\" => \"h\"\n                \"ձ\" => \"dz\"\n                \"ղ\" => \"gh\"\n                \"ճ\" => \"tch\"\n                \"մ\" => \"m\"\n                \"յ\" => \"y\"\n                \"ն\" => \"n\"\n                \"շ\" => \"sh\"\n                \"ո\" => \"vo\"\n                \"չ\" => \"ch\"\n                \"պ\" => \"p\"\n                \"ջ\" => \"j\"\n                \"ռ\" => \"r\"\n                \"ս\" => \"s\"\n                \"վ\" => \"v\"\n                \"տ\" => \"t\"\n                \"ր\" => \"r\"\n                \"ց\" => \"c\"\n                \"ւ\" => \"u\"\n                \"փ\" => \"ph\"\n                \"ք\" => \"q\"\n                \"օ\" => \"o\"\n                \"ֆ\" => \"f\"\n              ]\n              \"austrian\" => array:7 [\n                \"Ä\" => \"AE\"\n                \"Ö\" => \"OE\"\n                \"Ü\" => \"UE\"\n                \"ß\" => \"sz\"\n                \"ä\" => \"ae\"\n                \"ö\" => \"oe\"\n                \"ü\" => \"ue\"\n              ]\n              \"azerbaijani\" => array:14 [\n                \"Ə\" => \"E\"\n                \"Ç\" => \"C\"\n                \"Ğ\" => \"G\"\n                \"İ\" => \"I\"\n                \"Ş\" => \"S\"\n                \"Ö\" => \"O\"\n                \"Ü\" => \"U\"\n                \"ə\" => \"e\"\n                \"ç\" => \"c\"\n                \"ğ\" => \"g\"\n                \"ı\" => \"i\"\n                \"ş\" => \"s\"\n                \"ö\" => \"o\"\n                \"ü\" => \"u\"\n              ]\n              \"bulgarian\" => array:63 [\n                \"А\" => \"A\"\n                \"Б\" => \"B\"\n                \"В\" => \"V\"\n                \"Г\" => \"G\"\n                \"Д\" => \"D\"\n                \"Е\" => \"E\"\n                \"Ж\" => \"J\"\n                \"З\" => \"Z\"\n                \"И\" => \"I\"\n                \"Й\" => \"Y\"\n                \"К\" => \"K\"\n                \"Л\" => \"L\"\n                \"М\" => \"M\"\n                \"Н\" => \"N\"\n                \"О\" => \"O\"\n                \"П\" => \"P\"\n                \"Р\" => \"R\"\n                \"С\" => \"S\"\n                \"Т\" => \"T\"\n                \"У\" => \"U\"\n                \"Ф\" => \"F\"\n                \"Х\" => \"H\"\n                \"Ц\" => \"Ts\"\n                \"Ч\" => \"Ch\"\n                \"Ш\" => \"Sh\"\n                \"Щ\" => \"Sht\"\n                \"Ъ\" => \"A\"\n                \"Ь\" => \"I\"\n                \"Ю\" => \"Iu\"\n                \"Я\" => \"Ia\"\n                \"а\" => \"a\"\n                \"б\" => \"b\"\n                \"в\" => \"v\"\n                \"г\" => \"g\"\n                \"д\" => \"d\"\n                \"е\" => \"e\"\n                \"ж\" => \"j\"\n                \"з\" => \"z\"\n                \"и\" => \"i\"\n                \"й\" => \"y\"\n                \"к\" => \"k\"\n                \"л\" => \"l\"\n                \"м\" => \"m\"\n                \"н\" => \"n\"\n                \"о\" => \"o\"\n                \"п\" => \"p\"\n                \"р\" => \"r\"\n                \"с\" => \"s\"\n                \"т\" => \"t\"\n                \"у\" => \"u\"\n                \"ф\" => \"f\"\n                \"х\" => \"h\"\n                \"ц\" => \"ts\"\n                \"ч\" => \"ch\"\n                \"ш\" => \"sh\"\n                \"щ\" => \"sht\"\n                \"ъ\" => \"a\"\n                \"ь\" => \"i\"\n                \"ю\" => \"iu\"\n                \"я\" => \"ia\"\n                \"ия\" => \"ia\"\n                \"йо\" => \"\"\n                \"ьо\" => \"io\"\n              ]\n              \"burmese\" => array:114 [\n                \"က\" => \"k\"\n                \"\" => \"kh\"\n                \"\" => \"g\"\n                \"\" => \"ga\"\n                \"\" => \"ng\"\n                \"\" => \"s\"\n                \"\" => \"sa\"\n                \"\" => \"z\"\n                \"စျ\" => \"za\"\n                \"\" => \"ny\"\n                \"\" => \"t\"\n                \"\" => \"ta\"\n                \"\" => \"d\"\n                \"\" => \"da\"\n                \"\" => \"na\"\n                \"\" => \"t\"\n                \"\" => \"ta\"\n                \"\" => \"d\"\n                \"\" => \"da\"\n                \"\" => \"n\"\n                \"\" => \"p\"\n                \"\" => \"pa\"\n                \"\" => \"b\"\n                \"\" => \"ba\"\n                \"\" => \"m\"\n                \"\" => \"y\"\n                \"\" => \"ya\"\n                \"\" => \"l\"\n                \"\" => \"w\"\n                \"\" => \"th\"\n                \"\" => \"h\"\n                \"\" => \"la\"\n                \"\" => \"a\"\n                \"\" => \"y\"\n                \"\" => \"ya\"\n                \"\" => \"w\"\n                \"ြွ\" => \"yw\"\n                \"ျွ\" => \"ywa\"\n                \"\" => \"h\"\n                \"\" => \"e\"\n                \"\" => \"-e\"\n                \"\" => \"i\"\n                \"\" => \"-i\"\n                \"\" => \"u\"\n                \"\" => \"-u\"\n                \"\" => \"aw\"\n                \"သြော\" => \"aw\"\n                \"\" => \"aw\"\n                \"\" => \"ywae\"\n                \"\" => \"hnaik\"\n                \"\" => \"0\"\n                \"\" => \"1\"\n                \"\" => \"2\"\n                \"\" => \"3\"\n                \"\" => \"4\"\n                \"\" => \"5\"\n                \"\" => \"6\"\n                \"\" => \"7\"\n                \"\" => \"8\"\n                \"\" => \"9\"\n                \"\" => \"\"\n                \"\" => \"\"\n                \"\" => \"\"\n                \"\" => \"a\"\n                \"\" => \"a\"\n                \"\" => \"e\"\n                \"\" => \"e\"\n                \"\" => \"i\"\n                \"\" => \"i\"\n                \"ို\" => \"o\"\n                \"\" => \"u\"\n                \"\" => \"u\"\n                \"ေါင်\" => \"aung\"\n                \"ော\" => \"aw\"\n                \"ော်\" => \"aw\"\n                \"ေါ\" => \"aw\"\n                \"ေါ်\" => \"aw\"\n                \"\" => \"at\"\n                \"က်\" => \"et\"\n                \"ိုက်\" => \"aik\"\n                \"ောက်\" => \"auk\"\n                \"င်\" => \"in\"\n                \"ိုင်\" => \"aing\"\n                \"ောင်\" => \"aung\"\n                \"စ်\" => \"it\"\n                \"ည်\" => \"i\"\n                \"တ်\" => \"at\"\n                \"ိတ်\" => \"eik\"\n                \"ုတ်\" => \"ok\"\n                \"ွတ်\" => \"ut\"\n                \"ေတ်\" => \"it\"\n                \"ဒ်\" => \"d\"\n                \"ိုဒ်\" => \"ok\"\n                \"ုဒ်\" => \"ait\"\n                \"န်\" => \"an\"\n                \"ာန်\" => \"an\"\n                \"ိန်\" => \"ein\"\n                \"ုန်\" => \"on\"\n                \"ွန်\" => \"un\"\n                \"ပ်\" => \"at\"\n                \"ိပ်\" => \"eik\"\n                \"ုပ်\" => \"ok\"\n                \"ွပ်\" => \"ut\"\n                \"န်ုပ်\" => \"nub\"\n                \"မ်\" => \"an\"\n                \"ိမ်\" => \"ein\"\n                \"ုမ်\" => \"on\"\n                \"ွမ်\" => \"un\"\n                \"ယ်\" => \"e\"\n                \"ိုလ်\" => \"ol\"\n                \"ဉ်\" => \"in\"\n                \"\" => \"an\"\n                \"ိံ\" => \"ein\"\n                \"ုံ\" => \"on\"\n              ]\n              \"chinese\" => array:6933 [\n                \"\" => \"yan\"\n                \"\" => \"a\"\n                \"\" => \"po\"\n                \"\" => \"ai\"\n                \"\" => \"ai\"\n                \"\" => \"ai\"\n                \"\" => \"ai\"\n                \"\" => \"an\"\n                \"\" => \"ao\"\n                \"\" => \"ao\"\n                \"\" => \"niu\"\n                \"\" => \"ao\"\n                \"\" => \"ao\"\n                \"\" => \"ba\"\n                \"\" => \"ba\"\n                \"\" => \"pa\"\n                \"\" => \"ba\"\n                \"\" => \"ban\"\n                \"\" => \"pang\"\n                \"\" => \"bang\"\n                \"\" => \"pao\"\n                \"\" => \"pu\"\n                \"\" => \"pao\"\n                \"\" => \"pu\"\n                \"\" => \"bei\"\n                \"\" => \"pi\"\n                \"\" => \"bei\"\n                \"\" => \"bei\"\n                \"\" => \"bei\"\n                \"\" => \"bei\"\n                \"\" => \"bei\"\n                \"\" => \"ben\"\n                \"\" => \"beng\"\n                \"\" => \"bi\"\n                \"\" => \"mi\"\n                \"\" => \"pi\"\n                \"\" => \"mi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bi\"\n                \"\" => \"bian\"\n                \"\" => \"bian\"\n                \"\" => \"bian\"\n                \"\" => \"bian\"\n                \"便\" => \"bian\"\n                \"\" => \"bian\"\n                \"\" => \"bian\"\n                \"\" => \"biao\"\n                \"\" => \"shao\"\n                \"\" => \"biao\"\n                \"\" => \"biao\"\n                \"\" => \"biao\"\n                \"\" => \"biao\"\n                \"\" => \"bin\"\n                \"\" => \"bin\"\n                \"\" => \"bin\"\n                \"\" => \"bin\"\n                \"\" => \"ping\"\n                \"\" => \"bo\"\n                \"\" => \"bu\"\n                \"\" => \"bu\"\n                \"\" => \"bu\"\n                \"\" => \"bu\"\n                \"\" => \"pu\"\n                \"\" => \"bu\"\n                \"\" => \"ca\"\n                \"\" => \"can\"\n                \"\" => \"zang\"\n                \"\" => \"cao\"\n                \"\" => \"ce\"\n                \"\" => \"zha\"\n                \"\" => \"sha\"\n                \"\" => \"chai\"\n                \"\" => \"chan\"\n                \"\" => \"chan\"\n                \"\" => \"tan\"\n                \"\" => \"chan\"\n                \"\" => \"chan\"\n                \"\" => \"chang\"\n                \"\" => \"chang\"\n                \"\" => \"chang\"\n                \"\" => \"chang\"\n                \"\" => \"chang\"\n                \"\" => \"chang\"\n                \"\" => \"chao\"\n                \"\" => \"chao\"\n                \"\" => \"che\"\n                \"\" => \"chen\"\n                \"\" => \"chen\"\n                \"\" => \"chen\"\n                \"\" => \"cheng\"\n                \"\" => \"cheng\"\n                \"\" => \"cheng\"\n                \"\" => \"cheng\"\n                \"\" => \"cheng\"\n                \"\" => \"chi\"\n                \"\" => \"chi\"\n                \"\" => \"chi\"\n                \"\" => \"chi\"\n                \"\" => \"di\"\n                \"\" => \"chi\"\n                \"\" => \"zhong\"\n                \"\" => \"zhong\"\n                \"\" => \"chou\"\n                \"\" => \"chou\"\n                \"\" => \"chou\"\n                \"\" => \"chou\"\n                \"\" => \"chou\"\n                \"\" => \"chu\"\n                \"\" => \"chu\"\n                \"\" => \"zuo\"\n                \"\" => \"chuai\"\n                \"\" => \"chuan\"\n                \"\" => \"zhui\"\n                \"\" => \"ci\"\n                \"\" => \"zi\"\n                \"\" => \"si\"\n                \"\" => \"cong\"\n                \"\" => \"cou\"\n                \"\" => \"zan\"\n                \"\" => \"cuan\"\n                \"\" => \"zhui\"\n                \"\" => \"cui\"\n                \"\" => \"cuo\"\n                \"\" => \"cuo\"\n                \"\" => \"da\"\n                \"\" => \"da\"\n                \"\" => \"ta\"\n                \"\" => \"tai\"\n                \"\" => \"dai\"\n                \"\" => \"dai\"\n                \"\" => \"dai\"\n                \"\" => \"dan\"\n                \"\" => \"dan\"\n                \"\" => \"dao\"\n                \"\" => \"dao\"\n                \"\" => \"deng\"\n                \"\" => \"ti\"\n                \"\" => \"zhai\"\n                \"\" => \"ti\"\n                \"\" => \"dian\"\n                \"\" => \"dian\"\n                \"\" => \"dian\"\n                \"\" => \"dian\"\n                \"\" => \"tiao\"\n                \"\" => \"diao\"\n                \"\" => \"yi\"\n                \"\" => \"die\"\n                \"\" => \"die\"\n                \"\" => \"die\"\n                \"\" => \"die\"\n                \"\" => \"ding\"\n                \"\" => \"dong\"\n                \"\" => \"dong\"\n                \"\" => \"dong\"\n                \"\" => \"dong\"\n                \"\" => \"dong\"\n                \"\" => \"du\"\n                \"\" => \"duan\"\n                \"\" => \"dui\"\n                \"\" => \"dui\"\n                \"\" => \"tun\"\n                \"\" => \"duo\"\n                \"\" => \"duo\"\n                \"\" => \"tuo\"\n                \"\" => \"tuo\"\n                \"\" => \"tuo\"\n                \"\" => \"o\"\n                \"\" => \"e\"\n                \"\" => \"e\"\n                \"\" => \"e\"\n                \"\" => \"e\"\n                \"\" => \"e\"\n                \"\" => \"ea\"\n                \"\" => \"er\"\n                \"\" => \"er\"\n                \"\" => \"er\"\n                \"\" => \"fan\"\n                \"\" => \"pang\"\n                \"\" => \"fei\"\n                \"\" => \"fei\"\n                \"\" => \"fei\"\n                \"\" => \"fei\"\n                \"\" => \"fen\"\n                \"\" => \"fen\"\n                \"\" => \"fou\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"pu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"fu\"\n                \"\" => \"ka\"\n                \"\" => \"ga\"\n                \"\" => \"zha\"\n                \"\" => \"gai\"\n                \"\" => \"gai\"\n                \"\" => \"kang\"\n                \"\" => \"gang\"\n                \"\" => \"gang\"\n                \"\" => \"gao\"\n                \"\" => \"gao\"\n                \"\" => \"gao\"\n                \"\" => \"ge\"\n                \"\" => \"yi\"\n                \"\" => \"ge\"\n                \"\" => \"ge\"\n                \"\" => \"ge\"\n                \"\" => \"ge\"\n                \"\" => \"ju\"\n                \"\" => \"gou\"\n                \"\" => \"gou\"\n                \"\" => \"gou\"\n                \"\" => \"gou\"\n                \"\" => \"gu\"\n                \"\" => \"gu\"\n                \"\" => \"gu\"\n                \"\" => \"gu\"\n                \"\" => \"gu\"\n                \"\" => \"kuo\"\n                \"\" => \"guan\"\n                \"\" => \"lun\"\n                \"\" => \"guan\"\n                \"\" => \"wo\"\n                \"\" => \"guo\"\n                \"\" => \"guo\"\n                \"\" => \"guo\"\n                \"\" => \"ke\"\n                \"\" => \"hai\"\n                \"\" => \"han\"\n                \"\" => \"keng\"\n                \"\" => \"hang\"\n                \"\" => \"xiang\"\n                \"\" => \"ke\"\n                \"\" => \"he\"\n                \"\" => \"xia\"\n                \"\" => \"heng\"\n                \"\" => \"hong\"\n                \"\" => \"hong\"\n                \"\" => \"hong\"\n                \"\" => \"hou\"\n                \"\" => \"hu\"\n                \"\" => \"hu\"\n                \"\" => \"hu\"\n                \"\" => \"hu\"\n                \"\" => \"hu\"\n                \"\" => \"huan\"\n                \"\" => \"huan\"\n                \"\" => \"xun\"\n                \"\" => \"huan\"\n                \"\" => \"huan\"\n                \"\" => \"hui\"\n                \"\" => \"hui\"\n                \"\" => \"hui\"\n                \"\" => \"kui\"\n                \"\" => \"hui\"\n                \"\" => \"hui\"\n                \"\" => \"huo\"\n                \"\" => \"huo\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"xi\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"qi\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"ji\"\n                \"\" => \"qie\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"jia\"\n                \"\" => \"qia\"\n                \"\" => \"jia\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jia\"\n                \"\" => \"jiao\"\n                \"\" => \"qiu\"\n                \"\" => \"jiao\"\n                \"\" => \"jia\"\n                \"\" => \"qian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jian\"\n                \"\" => \"jiang\"\n                \"\" => \"jiang\"\n                \"\" => \"jiang\"\n                \"\" => \"jiang\"\n                \"\" => \"jiang\"\n                \"\" => \"jiang\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"qiao\"\n                \"\" => \"jiao\"\n                \"\" => \"xiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jiao\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"ju\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jie\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"槿\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jin\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jing\"\n                \"\" => \"jiong\"\n                \"\" => \"jiu\"\n                \"\" => \"jiu\"\n                \"\" => \"jiu\"\n                \"\" => \"jiu\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"ju\"\n                \"\" => \"quan\"\n                \"\" => \"juan\"\n                \"\" => \"juan\"\n                \"\" => \"juan\"\n                \"\" => \"juan\"\n                \"\" => \"juan\"\n                \"\" => \"juan\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jue\"\n                \"\" => \"jun\"\n                \"\" => \"jun\"\n                \"\" => \"jun\"\n                \"\" => \"jun\"\n                \"\" => \"ka\"\n                \"\" => \"ka\"\n                \"\" => \"ka\"\n                \"\" => \"ka\"\n                \"\" => \"kai\"\n                \"\" => \"kai\"\n                \"\" => \"kai\"\n                \"\" => \"kai\"\n                \"\" => \"kai\"\n                \"\" => \"kan\"\n                \"\" => \"kan\"\n                \"\" => \"kang\"\n                \"\" => \"kang\"\n                \"\" => \"kao\"\n                \"\" => \"kao\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ke\"\n                \"\" => \"ken\"\n                \"\" => \"kong\"\n                \"\" => \"kong\"\n                \"\" => \"kong\"\n                \"\" => \"kou\"\n                \"\" => \"kou\"\n                \"\" => \"kou\"\n                \"\" => \"ku\"\n                \"\" => \"ku\"\n                 …6466\n              ]\n              \"croatian\" => array:10 [ …10]\n              \"czech\" => array:18 [ …18]\n              \"danish\" => array:8 [ …8]\n              \"default\" => array:181 [ …181]\n              \"esperanto\" => array:12 [ …12]\n              \"estonian\" => array:12 [ …12]\n              \"finnish\" => array:4 [ …4]\n              \"french\" => array:32 [ …32]\n              \"georgian\" => array:33 [ …33]\n              \"german\" => array:7 [ …7]\n              \"greek\" => array:109 [ …109]\n              \"hindi\" => array:64 [ …64]\n              \"hungarian\" => array:18 [ …18]\n              \"italian\" => array:11 [ …11]\n              \"latvian\" => array:16 [ …16]\n              \"lithuanian\" => array:18 [ …18]\n              \"macedonian\" => array:62 [ …62]\n              \"norwegian\" => array:6 [ …6]\n              \"persian\" => array:32 [ …32]\n              \"polish\" => array:18 [ …18]\n              \"portuguese-brazil\" => array:181 [ …181]\n              \"romanian\" => array:14 [ …14]\n              \"russian\" => array:66 [ …66]\n              \"serbian\" => array:70 [ …70]\n              \"swedish\" => array:6 [ …6]\n              \"turkish\" => array:12 [ …12]\n              \"turkmen\" => array:16 [ …16]\n              \"ukrainian\" => array:8 [ …8]\n              \"vietnamese\" => array:90 [ …90]\n            ]\n          }\n          #options: array:7 [\n            \"regexp\" => \"/[^A-Za-z0-9]+/\"\n            \"separator\" => \"-\"\n            \"lowercase\" => true\n            \"lowercase_after_regexp\" => false\n            \"trim\" => true\n            \"strip_tags\" => false\n            \"rulesets\" => array:19 [\n              0 => \"default\"\n              1 => \"armenian\"\n              2 => \"azerbaijani\"\n              3 => \"burmese\"\n              4 => \"hindi\"\n              5 => \"georgian\"\n              6 => \"norwegian\"\n              7 => \"vietnamese\"\n              8 => \"ukrainian\"\n              9 => \"latvian\"\n              10 => \"finnish\"\n              11 => \"greek\"\n              12 => \"czech\"\n              13 => \"arabic\"\n              14 => \"turkish\"\n              15 => \"polish\"\n              16 => \"german\"\n              17 => \"russian\"\n              18 => \"romanian\"\n            ]\n          ]\n        }\n        -constrains: array:1 [\n          \"action\" => null\n        ]\n        -defaults: array:1 [\n          \"action\" => \"index\"\n        ]\n        -matchHost: false\n        -prefix: \"\"\n        -basePath: \"/\"\n        -compiled: \"/^(?:(?P<action>[^\\/]+)\\.html)?$/iu\"\n        -template: \"[<action>.html]\"\n        -options: array:1 [\n          \"action\" => null\n        ]\n        -uriFactory: Nyholm\\Psr7\\Factory\\Psr17Factory {#1350}\n        -patternRegistry: Spiral\\Router\\Registry\\DefaultPatternRegistry {#1351\n          -patterns: array:3 [\n            \"int\" => \"\\d+\"\n            \"integer\" => \"\\d+\"\n            \"uuid\" => \"[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}\"\n          ]\n        }\n      }\n      #matches: array:1 [\n        \"action\" => \"index\"\n      ]\n      #pattern: \"[<action>.html]\"\n      #verbs: array:7 [\n        0 => \"GET\"\n        1 => \"POST\"\n        2 => \"PUT\"\n        3 => \"PATCH\"\n        4 => \"OPTIONS\"\n        5 => \"HEAD\"\n        6 => \"DELETE\"\n      ]\n      #defaults: array:1 [\n        \"action\" => \"index\"\n      ]\n      -target: Spiral\\Router\\Target\\Controller {#69\n        -core: null\n        -handler: Spiral\\Router\\CoreHandler {#1544\n          -tracer: Spiral\\Telemetry\\NullTracer {#1337\n            -scope: Spiral\\Core\\Container {#4\n              -state: Spiral\\Core\\Internal\\State {#7\n                +bindings: & array:187 [\n                  \"Spiral\\Core\\Container\" => WeakReference {#8\n                    object: Spiral\\Core\\Container {#4}\n                  }\n                  \"Psr\\Container\\ContainerInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Core\\BinderInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Core\\FactoryInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Core\\ScopeInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Core\\ResolverInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Core\\InvokerInterface\" => \"Spiral\\Core\\Container\"\n                  \"Spiral\\Boot\\BootloadManager\\InitializerInterface\" => \"Spiral\\Boot\\BootloadManager\\Initializer\"\n                  \"Spiral\\Boot\\BootloadManager\\InvokerStrategyInterface\" => \"Spiral\\Boot\\BootloadManager\\DefaultInvokerStrategy\"\n                  \"Spiral\\Boot\\BootloadManager\\ClassesRegistry\" => Spiral\\Boot\\BootloadManager\\ClassesRegistry {#59\n                    -classes: array:59 [ …59]\n                  }\n                  \"Spiral\\Boot\\BootloadManager\\Initializer\" => Spiral\\Boot\\BootloadManager\\Initializer {#54\n                    #container: Spiral\\Core\\Container {#4}\n                    #binder: Spiral\\Core\\Container {#4}\n                    #bootloaders: Spiral\\Boot\\BootloadManager\\ClassesRegistry {#59}\n                  }\n                  \"Spiral\\Boot\\BootloadManager\\StrategyBasedBootloadManager\" => Spiral\\Boot\\BootloadManager\\StrategyBasedBootloadManager {#30\n                    -scope: Spiral\\Core\\Container {#4}\n                    #initializer: Spiral\\Boot\\BootloadManager\\Initializer {#54}\n                    -invoker: Spiral\\Boot\\BootloadManager\\DefaultInvokerStrategy {#42 …3}\n                  }\n                  \"Spiral\\Boot\\BootloadManagerInterface\" => Spiral\\Boot\\BootloadManager\\StrategyBasedBootloadManager {#30}\n                  \"Spiral\\Exceptions\\ExceptionHandlerInterface\" => App\\Exception\\Handler {#22\n                    +verbosity: Spiral\\Exceptions\\Verbosity {#21 …2}\n                    #renderers: & array:2 [ …2]\n                    #reporters: array:3 [ …3]\n                    #output: null\n                  }\n                  \"Spiral\\Exceptions\\ExceptionRendererInterface\" => App\\Exception\\Handler {#22}\n                  \"Spiral\\Exceptions\\ExceptionReporterInterface\" => App\\Exception\\Handler {#22}\n                  \"Spiral\\Exceptions\\ExceptionHandler\" => App\\Exception\\Handler {#22}\n                  \"Spiral\\Boot\\KernelInterface\" => App\\App {#19\n                    #finalizer: Spiral\\Boot\\Finalizer {#24\n                      -dispatcher: null\n                      -finalizers: array:5 [ …5]\n                    }\n                    #dispatchers: array:5 [ …5]\n                    -runningCallbacks: & array:1 [ …1]\n                    -bootingCallbacks: & []\n                    -bootedCallbacks: & []\n                    -bootstrappedCallbacks: & []\n                    #container: Spiral\\Core\\Container {#4}\n                    #exceptionHandler: App\\Exception\\Handler {#22}\n                    #bootloader: Spiral\\Boot\\BootloadManager\\StrategyBasedBootloadManager {#30}\n                    -bootingCallbacks: & []\n                    -bootedCallbacks: & []\n                  }\n                  \"Spiral\\Boot\\AbstractKernel\" => App\\App {#19}\n                  \"App\\App\" => App\\App {#19}\n                  \"Spiral\\Boot\\DirectoriesInterface\" => Spiral\\Boot\\Directories {#20\n                    -directories: array:11 [ …11]\n                  }\n                  \"Spiral\\Boot\\FinalizerInterface\" => Spiral\\Boot\\Finalizer {#24}\n                  \"Spiral\\Logger\\LogsInterface\" => array:2 [\n                    0 => \"Spiral\\Monolog\\LogFactory\"\n                    1 => true\n                  ]\n                  \"Spiral\\Config\\ConfigManager\" => Spiral\\Config\\ConfigManager {#57\n                    -data: array:17 [ …17]\n                    -defaults: array:26 [ …26]\n                    -instances: array:11 [ …11]\n                    -loader: Spiral\\Config\\Loader\\DirectoryLoader {#60 …2}\n                    -strict: true\n                  }\n                  \"Spiral\\Config\\ConfiguratorInterface\" => Spiral\\Config\\ConfigManager {#57}\n                  \"Spiral\\Tokenizer\\Bootloader\\TokenizerBootloader\" => Spiral\\Tokenizer\\Bootloader\\TokenizerBootloader {#39\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Tokenizer\\ScopedClassesInterface\" => \"Spiral\\Tokenizer\\ScopedClassLocator\"\n                  \"Spiral\\Tokenizer\\ClassesInterface\" => \"Spiral\\Tokenizer\\ClassLocator\"\n                  \"Spiral\\Tokenizer\\InvocationsInterface\" => \"Spiral\\Tokenizer\\InvocationLocator\"\n                  \"Spiral\\Boot\\EnvironmentInterface\" => Spiral\\Boot\\Environment {#25\n                    -id: null\n                    -values: array:61 [ …61]\n                    -overwrite: false\n                  }\n                  \"Spiral\\Prototype\\PrototypeRegistry\" => Spiral\\Prototype\\PrototypeRegistry {#105\n                    -dependencies: array:33 [ …33]\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Prototype\\Bootloader\\PrototypeBootloader\" => Spiral\\Prototype\\Bootloader\\PrototypeBootloader {#47\n                    -registry: Spiral\\Prototype\\PrototypeRegistry {#105}\n                  }\n                  \"Spiral\\Tokenizer\\Bootloader\\TokenizerListenerBootloader\" => Spiral\\Tokenizer\\Bootloader\\TokenizerListenerBootloader {#26\n                    -listeners: []\n                  }\n                  \"Spiral\\Console\\Bootloader\\ConsoleBootloader\" => Spiral\\Console\\Bootloader\\ConsoleBootloader {#107\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Console\\Console\" => array:2 [\n                    0 => \"Spiral\\Console\\Console\"\n                    1 => true\n                  ]\n                  \"Spiral\\Monolog\\Bootloader\\MonologBootloader\" => Spiral\\Monolog\\Bootloader\\MonologBootloader {#111\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"log.rotate\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Spiral\\Http\\Middleware\\ErrorHandlerMiddleware\\SuppressErrorsInterface\" => \"Spiral\\Http\\Middleware\\ErrorHandlerMiddleware\\EnvSuppressErrors\"\n                  \"Spiral\\Http\\ErrorHandler\\RendererInterface\" => \"App\\ErrorHandler\\ViewRenderer\"\n                  \"Spiral\\Snapshots\\SnapshotterInterface\" => array:2 [\n                    0 => \"Spiral\\Snapshots\\FileSnapshooter\"\n                    1 => true\n                  ]\n                  \"Spiral\\Cache\\CacheStorageProviderInterface\" => array:2 [\n                    0 => \"Spiral\\Cache\\CacheManager\"\n                    1 => true\n                  ]\n                  \"Spiral\\Cache\\CacheManager\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\GRPC\\Server\" => array:2 [\n                    0 => \"Spiral\\RoadRunner\\GRPC\\Server\"\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\GRPC\\InvokerInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunnerBridge\\GRPC\\LocatorInterface\" => array:2 [\n                    0 => \"Spiral\\RoadRunnerBridge\\GRPC\\ServiceLocator\"\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunnerBridge\\GRPC\\ProtoRepository\\ProtoFilesRepositoryInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Bootloader\\Http\\HttpBootloader\" => Spiral\\Bootloader\\Http\\HttpBootloader {#94\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Telemetry\\ClockInterface\" => array:2 [\n                    0 => \"Spiral\\Telemetry\\Clock\\SystemClock\"\n                    1 => true\n                  ]\n                  \"Spiral\\Serializer\\SerializerManager\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Serializer\\SerializerRegistryInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Serializer\\SerializerInterface\" => array:2 [\n                    0 => \"Spiral\\Serializer\\SerializerManager\"\n                    1 => true\n                  ]\n                  \"Spiral\\Queue\\SerializerRegistryInterface\" => array:2 [\n                    0 => \"Spiral\\Queue\\QueueRegistry\"\n                    1 => true\n                  ]\n                  \"Spiral\\Queue\\Failed\\FailedJobHandlerInterface\" => array:2 [\n                    0 => \"Spiral\\Queue\\Failed\\LogFailedJobHandler\"\n                    1 => true\n                  ]\n                  \"Spiral\\Bootloader\\I18nBootloader\" => Spiral\\Bootloader\\I18nBootloader {#97\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Symfony\\Contracts\\Translation\\TranslatorInterface\" => array:2 [\n                    0 => \"Spiral\\Translator\\TranslatorInterface\"\n                    1 => true\n                  ]\n                  \"Spiral\\Stempler\\Bootloader\\StemplerBootloader\" => Spiral\\Stempler\\Bootloader\\StemplerBootloader {#83\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Views\\Bootloader\\ViewsBootloader\" => Spiral\\Views\\Bootloader\\ViewsBootloader {#79\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Views\\GlobalVariables\" => array:2 [\n                    0 => \"Spiral\\Views\\GlobalVariables\"\n                    1 => true\n                  ]\n                  \"Spiral\\SendIt\\RendererInterface\" => array:2 [\n                    0 => \"Spiral\\SendIt\\Renderer\\ViewRenderer\"\n                    1 => true\n                  ]\n                  \"Spiral\\SendIt\\MailJob\" => array:2 [\n                    0 => \"Spiral\\SendIt\\MailJob\"\n                    1 => true\n                  ]\n                  \"Symfony\\Component\\Mailer\\MailerInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\SendIt\\TransportResolver\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\SendIt\\TransportResolverInterface\" => array:2 [\n                    0 => \"Spiral\\SendIt\\TransportResolver\"\n                    1 => true\n                  ]\n                  \"Spiral\\SendIt\\TransportRegistryInterface\" => array:2 [\n                    0 => \"Spiral\\SendIt\\TransportResolver\"\n                    1 => true\n                  ]\n                  \"Symfony\\Component\\Mailer\\Transport\\TransportInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Encrypter\\EncrypterInterface\" => \"Spiral\\Encrypter\\Encrypter\"\n                  \"Spiral\\Encrypter\\EncryptionInterface\" => array:2 [\n                    0 => \"Spiral\\Encrypter\\EncrypterFactory\"\n                    1 => true\n                  ]\n                  \"Spiral\\Validation\\Bootloader\\ValidationBootloader\" => Spiral\\Validation\\Bootloader\\ValidationBootloader {#103\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Validation\\ValidationProviderInterface\" => array:2 [\n                    0 => \"Spiral\\Validation\\ValidationProvider\"\n                    1 => true\n                  ]\n                  \"Spiral\\Validation\\ValidationInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Bootloader\\Security\\FiltersBootloader\" => Spiral\\Bootloader\\Security\\FiltersBootloader {#88\n                    -container: Spiral\\Core\\Container {#4}\n                    -binder: Spiral\\Core\\Container {#4}\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Filters\\Model\\FilterProviderInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Filters\\InputInterface\" => array:2 [\n                    0 => \"Spiral\\Filter\\InputScope\"\n                    1 => true\n                  ]\n                  \"Spiral\\Security\\ActorInterface\" => \"Spiral\\Security\\Actor\\Guest\"\n                  \"Spiral\\Security\\PermissionsInterface\" => array:2 [\n                    0 => \"Spiral\\Security\\PermissionManager\"\n                    1 => true\n                  ]\n                  \"Spiral\\Security\\RulesInterface\" => array:2 [\n                    0 => \"Spiral\\Security\\RuleManager\"\n                    1 => true\n                  ]\n                  \"Spiral\\Security\\GuardInterface\" => array:2 [\n                    0 => \"Spiral\\Security\\GuardScope\"\n                    1 => true\n                  ]\n                  \"Spiral\\Domain\\PermissionsProviderInterface\" => array:2 [\n                    0 => \"Spiral\\Domain\\GuardPermissionsProvider\"\n                    1 => true\n                  ]\n                  \"Spiral\\Router\\RouteInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Bootloader\\Http\\CookiesBootloader\" => Spiral\\Bootloader\\Http\\CookiesBootloader {#86\n                    -config: Spiral\\Config\\ConfigManager {#57}\n                  }\n                  \"Spiral\\Cookies\\CookieQueue\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Spiral\\Session\\SessionFactoryInterface\" => array:2 [\n                    0 => \"Spiral\\Session\\SessionFactory\"\n                    1 => true\n                  ]\n                  \"Spiral\\Pagination\\PaginationProviderInterface\" => array:2 [\n                    0 => \"Spiral\\Http\\PaginationFactory\"\n                    1 => true\n                  ]\n                  \"Spiral\\Router\\Bootloader\\AnnotatedRoutesBootloader\" => Spiral\\Router\\Bootloader\\AnnotatedRoutesBootloader {#81}\n                  \"Spiral\\Cycle\\Bootloader\\DatabaseBootloader\" => Spiral\\Cycle\\Bootloader\\DatabaseBootloader {#87}\n                  \"Cycle\\Database\\DatabaseManager\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Cycle\\Database\\DatabaseProviderInterface\" => array:2 [\n                    0 => \"Cycle\\Database\\DatabaseManager\"\n                    1 => true\n                  ]\n                  \"Cycle\\Database\\LoggerFactoryInterface\" => array:2 [\n                    0 => \"Spiral\\Cycle\\LoggerFactory\"\n                    1 => true\n                  ]\n                  \"Cycle\\Migrations\\Migrator\" => array:2 [\n                    0 => \"Cycle\\Migrations\\Migrator\"\n                    1 => true\n                  ]\n                  \"Cycle\\Migrations\\RepositoryInterface\" => array:2 [\n                    0 => \"Cycle\\Migrations\\FileRepository\"\n                    1 => true\n                  ]\n                  \"Spiral\\Cycle\\Bootloader\\SchemaBootloader\" => Spiral\\Cycle\\Bootloader\\SchemaBootloader {#74\n                    -defaultGenerators: array:3 [ …3]\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Cycle\\Annotated\\Embeddings\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cycle\\Annotated\\Entities\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cycle\\Annotated\\MergeColumns\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cycle\\Annotated\\TableInheritance\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cycle\\Annotated\\MergeIndexes\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cycle\\ORM\\ORMInterface\" => array:2 [\n                    0 => \"Cycle\\ORM\\ORM\"\n                    1 => true\n                  ]\n                  \"Cycle\\ORM\\EntityManagerInterface\" => array:2 [\n                    0 => \"Cycle\\ORM\\EntityManager\"\n                    1 => true\n                  ]\n                  \"Cycle\\ORM\\FactoryInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Cycle\\ORM\\SchemaInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Cocur\\Slugify\\SlugifyInterface\" => \"Cocur\\Slugify\\Slugify\"\n                  \"Spiral\\Bootloader\\DebugBootloader\" => Spiral\\Bootloader\\DebugBootloader {#52\n                    -collectors: array:3 [ …3]\n                    -factory: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Debug\\StateInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Spiral\\Debug\\StateCollector\\EnvironmentCollector\" => array:2 [\n                    0 => \"Spiral\\Debug\\StateCollector\\EnvironmentCollector\"\n                    1 => true\n                  ]\n                  \"Spiral\\Validator\\RulesInterface\" => array:2 [\n                    0 => \"Spiral\\Validator\\RulesProvider\"\n                    1 => true\n                  ]\n                  \"Spiral\\Filters\\FilterProviderInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Goridge\\RPC\\RPCInterface\" => array:2 [\n                    0 => \"Spiral\\Goridge\\RPC\\RPC\"\n                    1 => true\n                  ]\n                  \"Spiral\\Goridge\\RPC\\RPC\" => array:2 [\n                    0 => Closure(EnvironmentInterface $env): RPCInterface {#117 …2}\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\KeyValue\\FactoryInterface\" => array:2 [\n                    0 => Closure(RPCInterface $rpc) {#122 …1}\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\KeyValue\\StorageInterface\" => array:2 [\n                    0 => Closure(FactoryInterface $factory, string $driver) {#123 …1}\n                    1 => false\n                  ]\n                  \"Spiral\\RoadRunner\\Environment\" => Spiral\\RoadRunner\\Environment {#162\n                    -env: array:61 [ …61]\n                  }\n                  \"Spiral\\RoadRunner\\EnvironmentInterface\" => Spiral\\RoadRunner\\Environment {#162}\n                  \"Spiral\\RoadRunnerBridge\\RoadRunnerMode\" => Spiral\\RoadRunnerBridge\\RoadRunnerMode {#148\n                    +name: \"Http\"\n                    +value: \"http\"\n                  }\n                  \"Spiral\\RoadRunnerBridge\\Queue\\PipelineRegistryInterface\" => array:2 [\n                    0 => Closure(JobsInterface $jobs, JobsAdapterSerializer $serializer, array $pipelines, array $aliases): PipelineRegistryInterface {#129 …2}\n                    1 => false\n                  ]\n                  \"Spiral\\RoadRunnerBridge\\Queue\\JobsAdapterSerializer\" => array:2 [\n                    0 => Closure(SerializerRegistryInterface $registry) {#121 …1}\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\Jobs\\Serializer\\SerializerInterface\" => array:2 [\n                    0 => \"Spiral\\RoadRunnerBridge\\Queue\\JobsAdapterSerializer\"\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\Jobs\\JobsInterface\" => array:2 [\n                    0 => Closure(RPCInterface $rpc, SerializerInterface $serializer): Jobs {#128 …2}\n                    1 => true\n                  ]\n                  \"Spiral\\RoadRunner\\Jobs\\ConsumerInterface\" => array:2 [\n                    0 => Closure(JobsAdapterSerializer $serializer, WorkerInterface $worker): Consumer {#124 …2}\n                    1 => true\n                  ]\n                  \"Spiral\\Boot\\Environment\\DebugMode\" => Spiral\\Boot\\Environment\\DebugMode {#140\n                    +name: \"Enabled\"\n                  }\n                  \"Spiral\\Tokenizer\\TokenizerListenerRegistryInterface\" => Spiral\\Tokenizer\\Bootloader\\TokenizerListenerBootloader {#26}\n                  \"Spiral\\Attributes\\ReaderInterface\" => Spiral\\Attributes\\Composite\\SelectiveReader {#188\n                    #readers: array:2 [ …2]\n                  }\n                  \"Spiral\\Router\\GroupRegistry\" => Spiral\\Router\\GroupRegistry {#190\n                    -defaultGroup: \"web\"\n                    -groups: array:3 [ …3]\n                    -factory: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Debug\\StateCollector\\LogCollector\" => Spiral\\Debug\\StateCollector\\LogCollector {#146\n                    -logEvents: []\n                  }\n                  \"Spiral\\Logger\\ListenerRegistryInterface\" => Spiral\\Logger\\ListenerRegistry {#193\n                    -listeners: array:1 [ …1]\n                  }\n                  \"Spiral\\Debug\\StateCollector\\HttpCollector\" => Spiral\\Debug\\StateCollector\\HttpCollector {#161\n                    -request: Nyholm\\Psr7\\ServerRequest {#1349 …13}\n                  }\n                  \"Spiral\\Core\\ConfigsInterface\" => Spiral\\Config\\ConfigManager {#57}\n                  \"Sentry\\ClientInterface\" => Sentry\\Client {#228\n                    -options: Sentry\\Options {#207 …2}\n                    -transport: Sentry\\Transport\\HttpTransport {#230 …7}\n                    -logger: Psr\\Log\\NullLogger {#227}\n                    -integrations: array:8 [ …8]\n                    -representationSerializer: Sentry\\Serializer\\RepresentationSerializer {#279 …4}\n                    -stacktraceBuilder: Sentry\\StacktraceBuilder {#280 …1}\n                    -sdkIdentifier: \"sentry.php.spiral\"\n                    -sdkVersion: \"3.1.2\"\n                  }\n                  \"Spiral\\Session\\SessionScope\" => Spiral\\Session\\SessionScope {#294\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Psr\\Log\\LoggerInterface\" => Monolog\\Logger {#350\n                    #name: \"socket\"\n                    #handlers: & array:2 [ …2]\n                    #processors: array:1 [ …1]\n                    #microsecondTimestamps: true\n                    #timezone: DateTimeZone {#352 …3}\n                    #exceptionHandler: null\n                    -logDepth: 0\n                    -fiberLogDepth: WeakMap {#353}\n                    -detectCycles: true\n                  }\n                  \"Spiral\\Files\\FilesInterface\" => Spiral\\Files\\Files {#368\n                    -destructFiles: []\n                  }\n                  \"Spiral\\Snapshots\\FileSnapshot\" => Spiral\\Snapshots\\FileSnapshot {#356\n                    -directory: \"/root/repos/spiral-apps/filters-bridge/runtime//snapshots/\"\n                    -maxFiles: 25\n                    -verbosity: Spiral\\Exceptions\\Verbosity {#349\n                      +name: \"VERBOSE\"\n                      +value: 1\n                    }\n                    -renderer: Spiral\\Exceptions\\Renderer\\PlainRenderer {#357 …2}\n                    -files: Spiral\\Files\\Files {#368}\n                  }\n                  \"Spiral\\RoadRunnerBridge\\Http\\ErrorHandlerInterface\" => Spiral\\RoadRunnerBridge\\Http\\LogErrorHandler {#380\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Mailer\\MailerInterface\" => array:2 [\n                    0 => Closure(MailerConfig $config, QueueConnectionProviderInterface $provider): MailQueue {#335 …2}\n                    1 => true\n                  ]\n                  \"Spiral\\Queue\\QueueRegistry\" => Spiral\\Queue\\QueueRegistry {#337\n                    -handlers: array:1 [ …1]\n                    -serializers: []\n                    -container: Spiral\\Core\\Container {#4}\n                    -factory: Spiral\\Core\\Container {#4}\n                    -fallbackHandlers: Spiral\\Queue\\ContainerRegistry {#378 …2}\n                  }\n                  \"Spiral\\Router\\Loader\\LoaderRegistryInterface\" => Spiral\\Router\\Loader\\LoaderRegistry {#1336\n                    -loaders: array:1 [ …1]\n                  }\n                  \"Spiral\\Router\\Loader\\LoaderInterface\" => Spiral\\Router\\Loader\\DelegatingLoader {#1330\n                    -registry: Spiral\\Router\\Loader\\LoaderRegistry {#1336}\n                  }\n                  \"Spiral\\Router\\Loader\\Configurator\\RoutingConfigurator\" => Spiral\\Router\\Loader\\Configurator\\RoutingConfigurator {#1111\n                    -collection: Spiral\\Router\\RouteCollection {#1324 …1}\n                    -loader: Spiral\\Router\\Loader\\DelegatingLoader {#1330}\n                  }\n                  \"Psr\\Http\\Message\\UriFactoryInterface\" => Nyholm\\Psr7\\Factory\\Psr17Factory {#1350}\n                  \"Spiral\\Router\\Registry\\RoutePatternRegistryInterface\" => Spiral\\Router\\Registry\\DefaultPatternRegistry {#1351}\n                  \"Spiral\\Telemetry\\TracerFactoryProviderInterface\" => Spiral\\Telemetry\\ConfigTracerFactoryProvider {#1361\n                    -drivers: array:1 [ …1]\n                    -config: Spiral\\Telemetry\\Config\\TelemetryConfig {#1368 …1}\n                    -factory: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Telemetry\\TracerFactoryInterface\" => Spiral\\Telemetry\\NullTracerFactory {#1356\n                    -scope: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Router\\RouterInterface\" => Spiral\\Router\\Router {#1329\n                    -basePath: \"/\"\n                    -routes: array:5 [ …5]\n                    -default: null\n                    -uriHandler: Spiral\\Router\\UriHandler {#1342 …12}\n                    -container: Spiral\\Core\\Container {#4}\n                    -eventDispatcher: null\n                    -tracer: Spiral\\Telemetry\\NullTracer {#1337}\n                  }\n                  \"Spiral\\Validation\\ValidationProvider\" => Spiral\\Validation\\ValidationProvider {#1354\n                    -resolvers: array:1 [ …1]\n                    -invoker: Spiral\\Core\\Container {#4}\n                  }\n                  \"Inspector\\Inspector\" => Inspector\\Inspector {#1335\n                    #configuration: Inspector\\Configuration {#1343 …7}\n                    #transport: Inspector\\Transports\\AsyncTransport {#1359 …4}\n                    #transaction: null\n                  }\n                  \"Spiral\\Tokenizer\\Tokenizer\" => Spiral\\Tokenizer\\Tokenizer {#91\n                    -config: Spiral\\Tokenizer\\Config\\TokenizerConfig {#41 …1}\n                  }\n                  \"Spiral\\Tokenizer\\Listener\\ClassesLoaderInterface\" => Spiral\\Tokenizer\\Listener\\CachedClassesLoader {#99\n                    -reader: Spiral\\Attributes\\Composite\\SelectiveReader {#188}\n                    -memory: Spiral\\Boot\\Memory {#85 …2}\n                    -locator: Spiral\\Tokenizer\\Listener\\ClassLocatorByTarget {#104 …2}\n                    -invoker: Spiral\\Tokenizer\\Listener\\ListenerInvoker {#90}\n                    -readCache: true\n                  }\n                  \"middleware:web\" => array:2 [\n                    0 => Closure(PipelineFactory $factory): Pipeline {#327 …3}\n                    1 => false\n                  ]\n                  \"middleware:profiler\" => array:2 [\n                    0 => Closure(PipelineFactory $factory): Pipeline {#332 …3}\n                    1 => false\n                  ]\n                  \"middleware:api\" => array:2 [\n                    0 => Closure(PipelineFactory $factory): Pipeline {#336 …3}\n                    1 => false\n                  ]\n                  \"Spiral\\Boot\\DispatcherInterface\" => Spiral\\RoadRunnerBridge\\Http\\Dispatcher {#371\n                    -container: Spiral\\Core\\Container {#4}\n                    -errorHandler: Spiral\\RoadRunnerBridge\\Http\\LogErrorHandler {#380}\n                    -finalizer: Spiral\\Boot\\Finalizer {#24}\n                    -mode: Spiral\\RoadRunnerBridge\\RoadRunnerMode {#148}\n                  }\n                  \"Spiral\\RoadRunner\\Worker\" => Spiral\\RoadRunner\\Worker {#1375\n                    -relay: Spiral\\Goridge\\StreamRelay {#1378 …2}\n                    -logger: Spiral\\RoadRunner\\Logger {#1395}\n                  }\n                  \"Spiral\\RoadRunner\\WorkerInterface\" => Spiral\\RoadRunner\\Worker {#1375}\n                  \"Psr\\Http\\Message\\ServerRequestFactoryInterface\" => Nyholm\\Psr7\\Factory\\Psr17Factory {#93}\n                  \"Psr\\Http\\Message\\StreamFactoryInterface\" => Nyholm\\Psr7\\Factory\\Psr17Factory {#1397}\n                  \"Psr\\Http\\Message\\UploadedFileFactoryInterface\" => Nyholm\\Psr7\\Factory\\Psr17Factory {#1401}\n                  \"Spiral\\RoadRunner\\Http\\PSR7Worker\" => Spiral\\RoadRunner\\Http\\PSR7Worker {#1392\n                    +chunkSize: 0\n                    -httpWorker: Spiral\\RoadRunner\\Http\\HttpWorker {#333 …1}\n                    -requestFactory: Nyholm\\Psr7\\Factory\\Psr17Factory {#93}\n                    -streamFactory: Nyholm\\Psr7\\Factory\\Psr17Factory {#1397}\n                    -uploadsFactory: Nyholm\\Psr7\\Factory\\Psr17Factory {#1401}\n                    -originalServer: array:61 [ …61]\n                  }\n                  \"Spiral\\RoadRunner\\Http\\PSR7WorkerInterface\" => Spiral\\RoadRunner\\Http\\PSR7Worker {#1392}\n                  \"Spiral\\Telemetry\\TracerInterface\" => Spiral\\Telemetry\\NullTracer {#1337}\n                  \"Psr\\Http\\Server\\RequestHandlerInterface\" => Spiral\\Router\\Router {#1329}\n                  \"Psr\\Http\\Message\\ResponseFactoryInterface\" => Spiral\\Nyholm\\ResponseFactory {#1406\n                    -config: Spiral\\Http\\Config\\HttpConfig {#58\n                      #config: array:5 [\n                        \"basePath\" => \"/\"\n                        \"headers\" => array:1 [ …1]\n                        \"middleware\" => array:4 [ …4]\n                        \"chunkSize\" => null\n                        \"inputBags\" => []\n                      ]\n                    }\n                    -factory: Nyholm\\Psr7\\Factory\\Psr17Factory {#1409}\n                  }\n                  \"Spiral\\Translator\\Catalogue\\LoaderInterface\" => Spiral\\Translator\\Catalogue\\CatalogueLoader {#1432\n                    -config: Spiral\\Translator\\Config\\TranslatorConfig {#1414 …2}\n                    -logger: null\n                  }\n                  \"Spiral\\Boot\\MemoryInterface\" => Spiral\\Boot\\Memory {#1441\n                    -directory: \"/root/repos/spiral-apps/filters-bridge/runtime/cache\"\n                    -files: Spiral\\Files\\Files {#368}\n                  }\n                  \"Spiral\\Translator\\Catalogue\\CacheInterface\" => Spiral\\Translator\\MemoryCache {#1433\n                    -memory: Spiral\\Boot\\Memory {#1441}\n                  }\n                  \"Spiral\\Translator\\CatalogueManagerInterface\" => Spiral\\Translator\\Catalogue\\CatalogueManager {#1422\n                    -locales: array:2 [ …2]\n                    -cache: Spiral\\Translator\\MemoryCache {#1433}\n                    -catalogues: array:1 [ …1]\n                    -loader: Spiral\\Translator\\Catalogue\\CatalogueLoader {#1432}\n                  }\n                  \"Symfony\\Component\\Translation\\IdentityTranslator\" => Symfony\\Component\\Translation\\IdentityTranslator {#1416\n                    -locale: null\n                  }\n                  \"Spiral\\Translator\\Translator\" => Spiral\\Translator\\Translator {#1404\n                    -locale: \"en\"\n                    -config: Spiral\\Translator\\Config\\TranslatorConfig {#1414 …2}\n                    -catalogueManager: Spiral\\Translator\\Catalogue\\CatalogueManager {#1422}\n                    -identityTranslator: Symfony\\Component\\Translation\\IdentityTranslator {#1416}\n                    -dispatcher: null\n                  }\n                  \"Spiral\\Views\\GlobalVariablesInterface\" => Spiral\\Views\\GlobalVariables {#1444\n                    -variables: []\n                  }\n                  \"Spiral\\Views\\LoaderInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => true\n                  ]\n                  \"Spiral\\Translator\\TranslatorInterface\" => Spiral\\Translator\\Translator {#1404}\n                  \"Spiral\\Stempler\\StemplerEngine\" => Spiral\\Stempler\\StemplerEngine {#1453\n                    -classPrefix: \"__StemplerView__\"\n                    -builder: null\n                    -loader: null\n                    -container: Spiral\\Core\\Container {#4}\n                    -config: Spiral\\Stempler\\Config\\StemplerConfig {#1457 …1}\n                    -cache: null\n                  }\n                  \"Spiral\\Translator\\Views\\LocaleProcessor\" => Spiral\\Translator\\Views\\LocaleProcessor {#1461\n                    -translator: Spiral\\Translator\\Translator {#1404}\n                  }\n                  \"Spiral\\Stempler\\Directive\\RouteDirective\" => Spiral\\Stempler\\Directive\\RouteDirective {#1474\n                    -r: ReflectionObject {#1473 …7}\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Views\\ViewManager\" => Spiral\\Views\\ViewManager {#1437\n                    -loader: Spiral\\Views\\ViewLoader {#1435 …5}\n                    -cache: null\n                    -context: Spiral\\Views\\ViewContext {#1434 …1}\n                    -engines: & array:2 [ …2]\n                    -config: Spiral\\Views\\Config\\ViewsConfig {#1442 …1}\n                    -globalVariables: Spiral\\Views\\GlobalVariables {#1444}\n                  }\n                  \"Spiral\\Views\\ViewsInterface\" => Spiral\\Views\\ViewManager {#1437}\n                  \"Spiral\\Exceptions\\Verbosity\" => Spiral\\Exceptions\\Verbosity {#349}\n                  \"Spiral\\Http\\Http\" => Spiral\\Http\\Http {#1367\n                    -handler: Spiral\\Router\\Router {#1329}\n                    -tracerFactory: Spiral\\Telemetry\\NullTracerFactory {#1356}\n                    -config: Spiral\\Http\\Config\\HttpConfig {#58}\n                    -pipeline: Spiral\\Http\\Pipeline {#1403 …6}\n                    -responseFactory: Spiral\\Nyholm\\ResponseFactory {#1406}\n                    -container: Spiral\\Core\\Container {#4}\n                  }\n                  \"Spiral\\Telemetry\\SpanInterface\" => Spiral\\Telemetry\\Span {#1570\n                    -status: null\n                    -name: \"Controller [App\\Controller\\HomeController:index]\"\n                    -attributes: array:3 [ …3]\n                  }\n                  \"Psr\\Http\\Message\\ServerRequestInterface\" => Nyholm\\Psr7\\ServerRequest {#1545}\n                  \"Spiral\\Core\\CoreInterface\" => Spiral\\Core\\InterceptableCore {#1550\n                    -pipeline: Spiral\\Core\\InterceptorPipeline {#1546\n                      -core: null\n                      -interceptors: array:1 [\n                        0 => Spiral\\Filters\\Interceptor\\FilterInterceptor {#1556 …3}\n                      ]\n                      -position: 0\n                      -dispatcher: null\n                    }\n                    -core: Spiral\\Core\\Core {#1558\n                      #resolver: Spiral\\Core\\Container {#4}\n                      #container: Spiral\\Core\\Container {#4}\n                    }\n                  }\n                  \"SpiralPackages\\Profiler\\Storage\\StorageInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"SpiralPackages\\Profiler\\Driver\\DriverInterface\" => array:2 [\n                    0 => array:2 [ …2]\n                    1 => false\n                  ]\n                  \"Psr\\Http\\Message\\ResponseInterface\" => Nyholm\\Psr7\\Response {#1569\n                    -reasonPhrase: \"\"\n                    -statusCode: 200\n                    -headers: array:1 [ …1]\n                    -headerNames: array:1 [ …1]\n                    -protocol: \"1.1\"\n                    -stream: null\n                  }\n                  \"Spiral\\Queue\\QueueManager\" => Spiral\\Queue\\QueueManager {#1617\n                    -pipelines: array:1 [ …1]\n                    -config: Spiral\\Queue\\Config\\QueueConfig {#48 …1}\n                    -container: Spiral\\Core\\Container {#4}\n                    -factory: Spiral\\Core\\Container {#4}\n                    -dispatcher: null\n                  }\n                  \"Spiral\\Queue\\QueueConnectionProviderInterface\" => Spiral\\Queue\\QueueManager {#1617}\n                  \"Spiral\\Queue\\HandlerRegistryInterface\" => Spiral\\Queue\\QueueRegistry {#337}\n                  \"Spiral\\Queue\\Interceptor\\Consume\\Handler\" => Spiral\\Queue\\Interceptor\\Consume\\Handler {#1610\n                    -tracerFactory: Spiral\\Telemetry\\NullTracerFactory {#1356}\n                    -core: Spiral\\Core\\InterceptableCore {#1613 …2}\n                  }\n                  \"App\\Controller\\HomeController\" => App\\Controller\\HomeController {#1589\n                    -data: []\n                    -queue: Spiral\\Queue\\Queue {#1597 …1}\n                    -views: Spiral\\Views\\ViewManager {#1437}\n                  }\n                ]\n                +injectors: array:23 [\n                  \"Spiral\\Tokenizer\\ClassLocator\" => \"Spiral\\Tokenizer\\ClassLocatorInjector\"\n                  \"Spiral\\Tokenizer\\InvocationLocator\" => \"Spiral\\Tokenizer\\InvocationLocatorInjector\"\n                  \"Monolog\\Logger\" => \"Spiral\\Monolog\\LogFactory\"\n                  \"Psr\\SimpleCache\\CacheInterface\" => \"Spiral\\Cache\\Core\\CacheInjector\"\n                  \"Spiral\\Queue\\QueueInterface\" => \"Spiral\\Queue\\Core\\QueueInjector\"\n                  \"Spiral\\RoadRunnerBridge\\RoadRunnerMode\" => \"Spiral\\Boot\\Injector\\EnumInjector\"\n                  \"Spiral\\Boot\\Environment\\DebugMode\" => \"Spiral\\Boot\\Injector\\EnumInjector\"\n                  \"Spiral\\Filters\\Model\\FilterInterface\" => \"Spiral\\Bootloader\\Security\\FiltersBootloader\"\n                  \"Cycle\\Database\\DatabaseInterface\" => \"Spiral\\Cycle\\Injector\\DatabaseInjector\"\n                  \"Cycle\\ORM\\RepositoryInterface\" => \"Spiral\\Cycle\\Injector\\RepositoryInjector\"\n                  \"Spiral\\Filters\\FilterInterface\" => \"Spiral\\Filters\\Bootloader\\FiltersBootloader\"\n                  \"Spiral\\Sentry\\Config\\SentryConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Monolog\\Config\\MonologConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Telemetry\\Config\\TelemetryConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Queue\\Config\\QueueConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Tokenizer\\Config\\TokenizerConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Cycle\\Config\\CycleConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Http\\Config\\HttpConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Translator\\Config\\TranslatorConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Views\\Config\\ViewsConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Stempler\\Config\\StemplerConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                  \"Spiral\\Exceptions\\Verbosity\" => \"Spiral\\Boot\\Injector\\EnumInjector\"\n                  \"Spiral\\Bootloader\\Http\\JsonPayloadConfig\" => \"Spiral\\Core\\ConfigsInterface\"\n                ]\n                +finalizers: []\n              }\n              -resolver: Spiral\\Core\\Internal\\Resolver {#12\n                -factory: Spiral\\Core\\Internal\\Factory {#13\n                  -state: Spiral\\Core\\Internal\\State {#7}\n                  -binder: Spiral\\Core\\Internal\\Binder {#14\n                    #state: Spiral\\Core\\Internal\\State {#7}\n                    -container: Spiral\\Core\\Internal\\Container {#15\n                      -state: Spiral\\Core\\Internal\\State {#7}\n                      -factory: Spiral\\Core\\Internal\\Factory {#13}\n                    }\n                  }\n                  -invoker: Spiral\\Core\\Internal\\Invoker {#16\n                    -container: Spiral\\Core\\Internal\\Container {#15}\n                    -resolver: Spiral\\Core\\Internal\\Resolver {#12}\n                  }\n                  -container: Spiral\\Core\\Internal\\Container {#15}\n                  -resolver: Spiral\\Core\\Internal\\Resolver {#12}\n                  -tracer: Spiral\\Core\\Internal\\Tracer {#17\n                    -traces: & array:1 [\n                      0 => []\n                    ]\n                  }\n                  -scope: Spiral\\Core\\Internal\\Scope {#9\n                    -parent: null\n                    -parentScope: null\n                    -scopeName: \"root\"\n                  }\n                }\n                -container: Spiral\\Core\\Internal\\Container {#15}\n              }\n              -factory: Spiral\\Core\\Internal\\Factory {#13}\n              -container: Spiral\\Core\\Internal\\Container {#15}\n              -binder: Spiral\\Core\\Internal\\Binder {#14}\n              -invoker: Spiral\\Core\\Internal\\Invoker {#16}\n              -scope: Spiral\\Core\\Internal\\Scope {#9}\n              -config: Spiral\\Core\\Config {#5\n                +scope: \"Spiral\\Core\\Internal\\Scope\"\n                +scopedBindings: Spiral\\Core\\Internal\\Config\\StateStorage {#6\n                  -states: array:1 [\n                    \"root\" => Spiral\\Core\\Internal\\State {#7}\n                  ]\n                }\n                -rootLocked: false\n                +state: \"Spiral\\Core\\Internal\\State\"\n                +resolver: \"Spiral\\Core\\Internal\\Resolver\"\n                +factory: \"Spiral\\Core\\Internal\\Factory\"\n                +container: \"Spiral\\Core\\Internal\\Container\"\n                +binder: \"Spiral\\Core\\Internal\\Binder\"\n                +invoker: \"Spiral\\Core\\Internal\\Invoker\"\n                +tracer: \"Spiral\\Core\\Internal\\Tracer\"\n              }\n            }\n          }\n          -controller: null\n          -verbActions: null\n          -parameters: null\n          -core: Spiral\\Core\\InterceptableCore {#1550}\n          -scope: Spiral\\Core\\Container {#4}\n          -responseFactory: Spiral\\Nyholm\\ResponseFactory {#1406}\n        }\n        -verbActions: false\n        -defaults: array:1 [\n          \"action\" => null\n        ]\n        -constrains: array:1 [\n          \"action\" => null\n        ]\n        -defaultAction: \"index\"\n        -controller: \"App\\Controller\\HomeController\"\n      }\n      -requestHandler: Spiral\\Router\\CoreHandler {#1539\n        -tracer: Spiral\\Telemetry\\NullTracer {#1337}\n        -controller: \"App\\Controller\\HomeController\"\n        -action: \"index\"\n        -verbActions: false\n        -parameters: array:1 [\n          \"action\" => \"index\"\n        ]\n        -core: Spiral\\Core\\InterceptableCore {#1550}\n        -scope: Spiral\\Core\\Container {#4}\n        -responseFactory: Spiral\\Nyholm\\ResponseFactory {#1406}\n      }\n      #pipeline: Spiral\\Http\\Pipeline {#101\n        -position: 0\n        -tracer: Spiral\\Telemetry\\NullTracer {#1373\n          -scope: Spiral\\Core\\Container {#4}\n        }\n        -handler: null\n        -scope: Spiral\\Core\\Container {#4}\n        -dispatcher: null\n        #middleware: array:1 [\n          0 => Spiral\\Http\\Pipeline {#1374\n            -position: 0\n            -tracer: Spiral\\Telemetry\\NullTracer {#1383\n              -scope: Spiral\\Core\\Container {#4}\n            }\n            -handler: null\n            -scope: Spiral\\Core\\Container {#4}\n            -dispatcher: null\n            #middleware: array:2 [\n              0 => Spiral\\Profiler\\ProfilerMiddleware {#1384 …3}\n              1 => Spiral\\Http\\Pipeline {#1389 …6}\n            ]\n          }\n        ]\n      }\n      #middleware: array:1 [\n        0 => \"middleware:profiler\"\n      ]\n      #container: Spiral\\Core\\Container {#4}\n    }\n    \"routeName\" => \"html\"\n    \"matches\" => array:1 [\n      \"action\" => \"index\"\n    ]\n  ]\n  -cookieParams: array:4 [\n    \"_ga_TD1X69YDT5\" => \"GS1.1.1678132611.22.1.1678137856.0.0.0\"\n    \"_ga\" => \"GA1.1.734953706.1673627847\"\n    \"_lfa\" => \"LF1.1.f98950321ce4fe9c.1673271587691\"\n    \"theme\" => \"light\"\n  ]\n  -parsedBody: null\n  -queryParams: []\n  -serverParams: array:79 [\n    \"SHELL\" => \"/bin/bash\"\n    \"WSL2_GUI_APPS_ENABLED\" => \"1\"\n    \"WSL_DISTRO_NAME\" => \"Ubuntu-22.04\"\n    \"NODE_OPTIONS\" => \"--openssl-legacy-provider\"\n    \"NAME\" => \"ButschsterLpp\"\n    \"PWD\" => \"/root/repos/spiral-apps/filters-bridge\"\n    \"LOGNAME\" => \"root\"\n    \"HOME\" => \"/root\"\n    \"LANG\" => \"C.UTF-8\"\n    \"WSL_INTEROP\" => \"/run/WSL/29721_interop\"\n    \"LS_COLORS\" => \"rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:\"\n    \"WAYLAND_DISPLAY\" => \"wayland-0\"\n    \"LESSCLOSE\" => \"/usr/bin/lesspipe %s %s\"\n    \"TERM\" => \"xterm-256color\"\n    \"LESSOPEN\" => \"| /usr/bin/lesspipe %s\"\n    \"USER\" => \"root\"\n    \"DISPLAY\" => \":0\"\n    \"SHLVL\" => \"1\"\n    \"COMPOSER_ALLOW_SUPERUSER\" => \"1\"\n    \"XDG_RUNTIME_DIR\" => \"/mnt/wslg/runtime-dir\"\n    \"WSLENV\" => \"\"\n    \"XDG_DATA_DIRS\" => \"/usr/local/share:/usr/share:/var/lib/snapd/desktop\"\n    \"PATH\" => \"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files/dotnet/:/mnt/c/Program Files/Docker/Docker/resources/bin:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/ProgramData/ComposerSetup/bin:/mnt/c/Users/butsc/AppData/Local/Microsoft/WindowsApps:/mnt/c/Program Files/JetBrains/PhpStorm 2022.2.2/bin:/mnt/c/Users/butsc/AppData/Local/Programs/Microsoft VS Code/bin:/mnt/c/Users/butsc/Documents/PHP/8.1:/mnt/c/Users/butsc/OneDrive/PHP/composer:/mnt/c/Users/butsc/AppData/Roaming/Composer/vendor/bin:/snap/bin\"\n    \"HOSTTYPE\" => \"x86_64\"\n    \"PULSE_SERVER\" => \"unix:/mnt/wslg/PulseServer\"\n    \"_\" => \"./rr\"\n    \"RR_RELAY\" => \"pipes\"\n    \"RR_RPC\" => \"tcp://127.0.0.1:6002\"\n    \"RR_MODE\" => \"http\"\n    \"PHP_SELF\" => \"app.php\"\n    \"SCRIPT_NAME\" => \"app.php\"\n    \"SCRIPT_FILENAME\" => \"app.php\"\n    \"PATH_TRANSLATED\" => \"app.php\"\n    \"DOCUMENT_ROOT\" => \"\"\n    \"REQUEST_TIME_FLOAT\" => 1678272165.0609\n    \"REQUEST_TIME\" => 1678272165\n    \"argv\" => array:1 [\n      0 => \"app.php\"\n    ]\n    \"argc\" => 1\n    \"APP_ENV\" => \"local\"\n    \"DEBUG\" => \"true\"\n    \"TOKENIZER_CACHE_TARGETS\" => \"true\"\n    \"ENCRYPTER_KEY\" => \"def00000c7cb5691f7d052a7d4d1aea220b23db12a2a0f9d5be80c044e6cc5c2671d049decfe970c545c7d457f8e7edf2f979acefd988a926bcfa84dc042873db3a19dc6\"\n    \"SAFE_MIGRATIONS\" => \"true\"\n    \"QUEUE_CONNECTION\" => \"sync\"\n    \"MONOLOG_DEFAULT_CHANNEL\" => \"socket\"\n    \"MONOLOG_DEFAULT_LEVEL\" => \"DEBUG\"\n    \"MONOLOG_SOCKET_HOST\" => \"127.0.0.1:9913\"\n    \"CACHE_STORAGE\" => \"local\"\n    \"SESSION_LIFETIME\" => \"86400\"\n    \"SESSION_COOKIE\" => \"sid\"\n    \"MAILER_DSN\" => \"smtp://127.0.0.1:1025\"\n    \"MAILER_PIPELINE\" => \"local\"\n    \"MAILER_FROM\" => \"Spiral <sendit@local.host>\"\n    \"STORAGE_DEFAULT\" => \"default\"\n    \"CYCLE_SCHEMA_CACHE\" => \"true\"\n    \"CYCLE_SCHEMA_WARMUP\" => \"false\"\n    \"SENTRY_DSN\" => \"http://tsfsdfsdfsdfcsdf@127.0.0.1:8082/1\"\n    \"VAR_DUMPER_FORMAT\" => \"server\"\n    \"VAR_DUMPER_SERVER\" => \"127.0.0.1:9912\"\n    \"PROFILER_ENDPOINT\" => \"http://127.0.0.1:8082/api/profiler/store\"\n    \"PROFILER_APP_NAME\" => \"My super app\"\n    \"REQUEST_URI\" => \"http://127.0.0.1:8080/\"\n    \"REMOTE_ADDR\" => \"127.0.0.1\"\n    \"REQUEST_METHOD\" => \"GET\"\n    \"HTTP_USER_AGENT\" => \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\"\n    \"HTTP_CACHE_CONTROL\" => \"max-age=0\"\n    \"HTTP_SEC_CH_UA_PLATFORM\" => \""Windows"\"\n    \"HTTP_UPGRADE_INSECURE_REQUESTS\" => \"1\"\n    \"HTTP_SEC_FETCH_SITE\" => \"none\"\n    \"HTTP_CONNECTION\" => \"keep-alive\"\n    \"HTTP_SEC_CH_UA\" => \""Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"\"\n    \"HTTP_SEC_CH_UA_MOBILE\" => \"?0\"\n    \"HTTP_ACCEPT_LANGUAGE\" => \"en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,ka;q=0.6\"\n    \"HTTP_COOKIE\" => \"_ga=GA1.1.734953706.1673627847; _lfa=LF1.1.f98950321ce4fe9c.1673271587691; theme=light; _ga_TD1X69YDT5=GS1.1.1678132611.22.1.1678137856.0.0.0\"\n    \"HTTP_ACCEPT\" => \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\"\n    \"HTTP_SEC_FETCH_DEST\" => \"document\"\n    \"HTTP_ACCEPT_ENCODING\" => \"gzip, deflate, br\"\n    \"HTTP_SEC_FETCH_MODE\" => \"navigate\"\n    \"HTTP_SEC_FETCH_USER\" => \"?1\"\n  ]\n  -uploadedFiles: []\n  -headers: array:16 [\n    \"Host\" => array:1 [\n      0 => \"127.0.0.1:8080\"\n    ]\n    \"User-Agent\" => array:1 [\n      0 => \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\"\n    ]\n    \"Cache-Control\" => array:1 [\n      0 => \"max-age=0\"\n    ]\n    \"Sec-Ch-Ua-Platform\" => array:1 [\n      0 => \""Windows"\"\n    ]\n    \"Upgrade-Insecure-Requests\" => array:1 [\n      0 => \"1\"\n    ]\n    \"Sec-Fetch-Site\" => array:1 [\n      0 => \"none\"\n    ]\n    \"Connection\" => array:1 [\n      0 => \"keep-alive\"\n    ]\n    \"Sec-Ch-Ua\" => array:1 [\n      0 => \""Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"\"\n    ]\n    \"Sec-Ch-Ua-Mobile\" => array:1 [\n      0 => \"?0\"\n    ]\n    \"Accept-Language\" => array:1 [\n      0 => \"en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,ka;q=0.6\"\n    ]\n    \"Cookie\" => array:1 [\n      0 => \"_ga=GA1.1.734953706.1673627847; _lfa=LF1.1.f98950321ce4fe9c.1673271587691; theme=light; _ga_TD1X69YDT5=GS1.1.1678132611.22.1.1678137856.0.0.0\"\n    ]\n    \"Accept\" => array:1 [\n      0 => \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\"\n    ]\n    \"Sec-Fetch-Dest\" => array:1 [\n      0 => \"document\"\n    ]\n    \"Accept-Encoding\" => array:1 [\n      0 => \"gzip, deflate, br\"\n    ]\n    \"Sec-Fetch-Mode\" => array:1 [\n      0 => \"navigate\"\n    ]\n    \"Sec-Fetch-User\" => array:1 [\n      0 => \"?1\"\n    ]\n  ]\n  -headerNames: array:16 [\n    \"host\" => \"Host\"\n    \"user-agent\" => \"User-Agent\"\n    \"cache-control\" => \"Cache-Control\"\n    \"sec-ch-ua-platform\" => \"Sec-Ch-Ua-Platform\"\n    \"upgrade-insecure-requests\" => \"Upgrade-Insecure-Requests\"\n    \"sec-fetch-site\" => \"Sec-Fetch-Site\"\n    \"connection\" => \"Connection\"\n    \"sec-ch-ua\" => \"Sec-Ch-Ua\"\n    \"sec-ch-ua-mobile\" => \"Sec-Ch-Ua-Mobile\"\n    \"accept-language\" => \"Accept-Language\"\n    \"cookie\" => \"Cookie\"\n    \"accept\" => \"Accept\"\n    \"sec-fetch-dest\" => \"Sec-Fetch-Dest\"\n    \"accept-encoding\" => \"Accept-Encoding\"\n    \"sec-fetch-mode\" => \"Sec-Fetch-Mode\"\n    \"sec-fetch-user\" => \"Sec-Fetch-User\"\n  ]\n  -protocol: \"1.1\"\n  -stream: null\n  -method: \"GET\"\n  -requestTarget: null\n  -uri: Nyholm\\Psr7\\Uri {#119\n    -scheme: \"http\"\n    -userInfo: \"\"\n    -host: \"127.0.0.1\"\n    -port: 8080\n    -path: \"/\"\n    -query: \"\"\n    -fragment: \"\"\n  }\n}\n
\n" diff --git a/src/shared/types/events.ts b/src/shared/types/events.ts new file mode 100644 index 00000000..60d6bc09 --- /dev/null +++ b/src/shared/types/events.ts @@ -0,0 +1,37 @@ +import { OneOfValues } from "./generics"; + +// TODO: add T prefix to all types + +export enum EVENT_TYPES { + VAR_DUMP = "var-dump", + SMTP = "smtp", + SENTRY = "sentry", + PROFILER = "profiler", + MONOLOG = "monolog", + INSPECTOR = "inspector", + HTTP_DUMP = "http-dump", + RAY_DUMP = "ray", +} + +export type EventId = string; + +export type EventType = OneOfValues; + +export interface ServerEvent { + uuid: EventId, + type: EventType | string, + payload: T, + server_name?: string, + project_id: string | null, + timestamp?: number // unavailable for some ray dump events +} + +export interface NormalizedEvent { + id: EventId, + type: EventType | string, + labels: string[], + origin: object | null, + serverName: string, + date: Date | null, + payload: T +} diff --git a/src/shared/types/generics.ts b/src/shared/types/generics.ts new file mode 100644 index 00000000..42fd97d4 --- /dev/null +++ b/src/shared/types/generics.ts @@ -0,0 +1 @@ +export type OneOfValues = T[keyof T]; diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts new file mode 100644 index 00000000..0416df32 --- /dev/null +++ b/src/shared/types/index.ts @@ -0,0 +1,4 @@ +export * from "./events"; +export * from "./generics"; +export * from "./local-storage"; +export * from "./partials"; diff --git a/src/shared/types/local-storage.ts b/src/shared/types/local-storage.ts new file mode 100644 index 00000000..1e6daa3a --- /dev/null +++ b/src/shared/types/local-storage.ts @@ -0,0 +1,6 @@ + +export enum LOCAL_STORAGE_KEYS { + CACHED_EVENTS = "cached_events", + THEME = "theme", + NAVBAR = "navbar", +} diff --git a/src/shared/types/partials.ts b/src/shared/types/partials.ts new file mode 100644 index 00000000..cf6840dd --- /dev/null +++ b/src/shared/types/partials.ts @@ -0,0 +1,21 @@ +export interface Source { + file: string, + name: string, + line: string, + file_excerpt?: boolean +} + +export interface Attachment { + id: string, + name: string, + size: number, + mime: string, + uri: string +} + +export enum GraphTypes { + CPU = 'cpu' , + MEMORY_CHANGE = 'pmu', + MEMORY = 'mu', + CALLS = 'calls', +} diff --git a/components/CodeSnippet/CodeSnippet.stories.ts b/src/shared/ui/code-snippet/code-snippet.stories.ts similarity index 53% rename from components/CodeSnippet/CodeSnippet.stories.ts rename to src/shared/ui/code-snippet/code-snippet.stories.ts index 99317f4e..1ac248cd 100644 --- a/components/CodeSnippet/CodeSnippet.stories.ts +++ b/src/shared/ui/code-snippet/code-snippet.stories.ts @@ -1,10 +1,10 @@ import { Meta, Story } from "@storybook/vue3"; -import { EVENT_TYPES } from "~/config/constants"; -import CodeSnippet from "~/components/CodeSnippet/CodeSnippet.vue"; -import { HTML } from '@/mocks/mail'; +import { HTMLCode, PHPCode } from '../../mocks'; +import { EVENT_TYPES } from "../../types"; +import CodeSnippet from "./code-snippet.vue"; export default { - title: "Components/CodeSnippet", + title: "Shared/CodeSnippet", component: CodeSnippet, } as Meta; @@ -18,6 +18,12 @@ const Template: Story = (args) => ({ template: ``, }); +export const Default = Template.bind({}); +Default.args = { + code: "Hello World!", + language: 'text' +}; + export const Object = Template.bind({}); Object.args = { code: { @@ -36,31 +42,10 @@ Object.args = { export const HTMLString = Template.bind({}); HTMLString.args = { - code: HTML, + code: HTMLCode, language: 'html' }; -const PHPCode = `use RoadRunner\\Centrifugo\\CentrifugoApiInterface; - -final class UserBanService -{ - public function __construct( - private readonly UserRepository $repository, - private readonly CentrifugoApiInterface $ws - ) {} - - public function handle(string $userUuid): void - { - $user = $this->repository->findByPK($userUuid); - - // Ban user... - - // Disconnect from webscoket server - $this->ws->disconnect($user->getId()); - } -} -` - export const PHPString = Template.bind({}); PHPString.args = { code: PHPCode, diff --git a/src/shared/ui/code-snippet/code-snippet.vue b/src/shared/ui/code-snippet/code-snippet.vue new file mode 100644 index 00000000..a5eea041 --- /dev/null +++ b/src/shared/ui/code-snippet/code-snippet.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/shared/ui/code-snippet/index.ts b/src/shared/ui/code-snippet/index.ts new file mode 100644 index 00000000..6a81de7e --- /dev/null +++ b/src/shared/ui/code-snippet/index.ts @@ -0,0 +1,3 @@ +import CodeSnippet from "./code-snippet.vue"; + +export { CodeSnippet } diff --git a/components/SmtpAttachment/SmtpAttachment.stories.ts b/src/shared/ui/file-attachment/file-attachment.stories.ts similarity index 57% rename from components/SmtpAttachment/SmtpAttachment.stories.ts rename to src/shared/ui/file-attachment/file-attachment.stories.ts index 376799f6..1976245f 100644 --- a/components/SmtpAttachment/SmtpAttachment.stories.ts +++ b/src/shared/ui/file-attachment/file-attachment.stories.ts @@ -1,26 +1,26 @@ import {Meta, Story} from "@storybook/vue3"; -import SmtpAttachment from '~/components/SmtpAttachment/SmtpAttachment.vue'; +import FileAttachment from './file-attachment.vue'; export default { - title: "Components/Attachment", - component: SmtpAttachment -} as Meta; + title: "Shared/FileAttachment", + component: FileAttachment +} as Meta; const Template: Story = (args) => ({ - components: {SmtpAttachment}, + components: {FileAttachment}, setup() { return { args, }; }, template: ` - `, + `, }); export const Default = Template.bind({}); Default.args = { - event: {id: 'cbdd3296-1e25-4191-9f52-0e2d7e7d6aae'}, + eventId: 'cbdd3296-1e25-4191-9f52-0e2d7e7d6aae', attachment: { id: 'cbdd3296-1e25-4191-9f52-0e2d7e7d6aae', name: 'attachment.txt', diff --git a/src/shared/ui/file-attachment/file-attachment.vue b/src/shared/ui/file-attachment/file-attachment.vue new file mode 100644 index 00000000..9496ae7f --- /dev/null +++ b/src/shared/ui/file-attachment/file-attachment.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/shared/ui/file-attachment/index.ts b/src/shared/ui/file-attachment/index.ts new file mode 100644 index 00000000..374a13a0 --- /dev/null +++ b/src/shared/ui/file-attachment/index.ts @@ -0,0 +1,3 @@ +import FileAttachment from "./file-attachment.vue"; + +export { FileAttachment }; diff --git a/components/IconSvg/collapsed.svg b/src/shared/ui/icon-svg/icon-svg-originals/collapsed.svg similarity index 100% rename from components/IconSvg/collapsed.svg rename to src/shared/ui/icon-svg/icon-svg-originals/collapsed.svg diff --git a/components/IconSvg/connected.svg b/src/shared/ui/icon-svg/icon-svg-originals/connected.svg similarity index 100% rename from components/IconSvg/connected.svg rename to src/shared/ui/icon-svg/icon-svg-originals/connected.svg diff --git a/components/IconSvg/copy.svg b/src/shared/ui/icon-svg/icon-svg-originals/copy.svg similarity index 100% rename from components/IconSvg/copy.svg rename to src/shared/ui/icon-svg/icon-svg-originals/copy.svg diff --git a/components/IconSvg/dd.svg b/src/shared/ui/icon-svg/icon-svg-originals/dd.svg similarity index 100% rename from components/IconSvg/dd.svg rename to src/shared/ui/icon-svg/icon-svg-originals/dd.svg diff --git a/components/IconSvg/desktop-device.svg b/src/shared/ui/icon-svg/icon-svg-originals/desktop-device.svg similarity index 100% rename from components/IconSvg/desktop-device.svg rename to src/shared/ui/icon-svg/icon-svg-originals/desktop-device.svg diff --git a/components/IconSvg/disconnected.svg b/src/shared/ui/icon-svg/icon-svg-originals/disconnected.svg similarity index 100% rename from components/IconSvg/disconnected.svg rename to src/shared/ui/icon-svg/icon-svg-originals/disconnected.svg diff --git a/components/IconSvg/docs.svg b/src/shared/ui/icon-svg/icon-svg-originals/docs.svg similarity index 100% rename from components/IconSvg/docs.svg rename to src/shared/ui/icon-svg/icon-svg-originals/docs.svg diff --git a/components/IconSvg/events.svg b/src/shared/ui/icon-svg/icon-svg-originals/events.svg similarity index 100% rename from components/IconSvg/events.svg rename to src/shared/ui/icon-svg/icon-svg-originals/events.svg diff --git a/components/IconSvg/fullscreen.svg b/src/shared/ui/icon-svg/icon-svg-originals/fullscreen.svg similarity index 100% rename from components/IconSvg/fullscreen.svg rename to src/shared/ui/icon-svg/icon-svg-originals/fullscreen.svg diff --git a/components/IconSvg/github.svg b/src/shared/ui/icon-svg/icon-svg-originals/github.svg similarity index 100% rename from components/IconSvg/github.svg rename to src/shared/ui/icon-svg/icon-svg-originals/github.svg diff --git a/components/IconSvg/heartBeat.svg b/src/shared/ui/icon-svg/icon-svg-originals/heartBeat.svg similarity index 100% rename from components/IconSvg/heartBeat.svg rename to src/shared/ui/icon-svg/icon-svg-originals/heartBeat.svg diff --git a/components/IconSvg/host.svg b/src/shared/ui/icon-svg/icon-svg-originals/host.svg similarity index 100% rename from components/IconSvg/host.svg rename to src/shared/ui/icon-svg/icon-svg-originals/host.svg diff --git a/components/IconSvg/http-dumps.svg b/src/shared/ui/icon-svg/icon-svg-originals/http-dumps.svg similarity index 100% rename from components/IconSvg/http-dumps.svg rename to src/shared/ui/icon-svg/icon-svg-originals/http-dumps.svg diff --git a/components/IconSvg/inspector.svg b/src/shared/ui/icon-svg/icon-svg-originals/inspector.svg similarity index 100% rename from components/IconSvg/inspector.svg rename to src/shared/ui/icon-svg/icon-svg-originals/inspector.svg diff --git a/components/IconSvg/lock-off.svg b/src/shared/ui/icon-svg/icon-svg-originals/lock-off.svg similarity index 100% rename from components/IconSvg/lock-off.svg rename to src/shared/ui/icon-svg/icon-svg-originals/lock-off.svg diff --git a/components/IconSvg/lock.svg b/src/shared/ui/icon-svg/icon-svg-originals/lock.svg similarity index 100% rename from components/IconSvg/lock.svg rename to src/shared/ui/icon-svg/icon-svg-originals/lock.svg diff --git a/components/IconSvg/logo.svg b/src/shared/ui/icon-svg/icon-svg-originals/logo.svg similarity index 100% rename from components/IconSvg/logo.svg rename to src/shared/ui/icon-svg/icon-svg-originals/logo.svg diff --git a/components/IconSvg/logout.svg b/src/shared/ui/icon-svg/icon-svg-originals/logout.svg similarity index 100% rename from components/IconSvg/logout.svg rename to src/shared/ui/icon-svg/icon-svg-originals/logout.svg diff --git a/components/IconSvg/minus.svg b/src/shared/ui/icon-svg/icon-svg-originals/minus.svg similarity index 100% rename from components/IconSvg/minus.svg rename to src/shared/ui/icon-svg/icon-svg-originals/minus.svg diff --git a/components/IconSvg/mobile-device.svg b/src/shared/ui/icon-svg/icon-svg-originals/mobile-device.svg similarity index 100% rename from components/IconSvg/mobile-device.svg rename to src/shared/ui/icon-svg/icon-svg-originals/mobile-device.svg diff --git a/components/IconSvg/moon.svg b/src/shared/ui/icon-svg/icon-svg-originals/moon.svg similarity index 100% rename from components/IconSvg/moon.svg rename to src/shared/ui/icon-svg/icon-svg-originals/moon.svg diff --git a/components/IconSvg/newScreen.svg b/src/shared/ui/icon-svg/icon-svg-originals/newScreen.svg similarity index 100% rename from components/IconSvg/newScreen.svg rename to src/shared/ui/icon-svg/icon-svg-originals/newScreen.svg diff --git a/components/IconSvg/plus.svg b/src/shared/ui/icon-svg/icon-svg-originals/plus.svg similarity index 100% rename from components/IconSvg/plus.svg rename to src/shared/ui/icon-svg/icon-svg-originals/plus.svg diff --git a/components/IconSvg/profiler.svg b/src/shared/ui/icon-svg/icon-svg-originals/profiler.svg similarity index 100% rename from components/IconSvg/profiler.svg rename to src/shared/ui/icon-svg/icon-svg-originals/profiler.svg diff --git a/components/IconSvg/screen.svg b/src/shared/ui/icon-svg/icon-svg-originals/screen.svg similarity index 100% rename from components/IconSvg/screen.svg rename to src/shared/ui/icon-svg/icon-svg-originals/screen.svg diff --git a/components/IconSvg/sentry.svg b/src/shared/ui/icon-svg/icon-svg-originals/sentry.svg similarity index 100% rename from components/IconSvg/sentry.svg rename to src/shared/ui/icon-svg/icon-svg-originals/sentry.svg diff --git a/components/IconSvg/settings.svg b/src/shared/ui/icon-svg/icon-svg-originals/settings.svg similarity index 100% rename from components/IconSvg/settings.svg rename to src/shared/ui/icon-svg/icon-svg-originals/settings.svg diff --git a/components/IconSvg/smtp.svg b/src/shared/ui/icon-svg/icon-svg-originals/smtp.svg similarity index 100% rename from components/IconSvg/smtp.svg rename to src/shared/ui/icon-svg/icon-svg-originals/smtp.svg diff --git a/components/IconSvg/sun.svg b/src/shared/ui/icon-svg/icon-svg-originals/sun.svg similarity index 100% rename from components/IconSvg/sun.svg rename to src/shared/ui/icon-svg/icon-svg-originals/sun.svg diff --git a/components/IconSvg/tablet-device.svg b/src/shared/ui/icon-svg/icon-svg-originals/tablet-device.svg similarity index 100% rename from components/IconSvg/tablet-device.svg rename to src/shared/ui/icon-svg/icon-svg-originals/tablet-device.svg diff --git a/components/IconSvg/times.svg b/src/shared/ui/icon-svg/icon-svg-originals/times.svg similarity index 100% rename from components/IconSvg/times.svg rename to src/shared/ui/icon-svg/icon-svg-originals/times.svg diff --git a/components/IconSvg/trash-bin.svg b/src/shared/ui/icon-svg/icon-svg-originals/trash-bin.svg similarity index 100% rename from components/IconSvg/trash-bin.svg rename to src/shared/ui/icon-svg/icon-svg-originals/trash-bin.svg diff --git a/components/IconSvg/IconSvg.stories.ts b/src/shared/ui/icon-svg/icon-svg.stories.ts similarity index 92% rename from components/IconSvg/IconSvg.stories.ts rename to src/shared/ui/icon-svg/icon-svg.stories.ts index 2c2c946b..8a3a9943 100644 --- a/components/IconSvg/IconSvg.stories.ts +++ b/src/shared/ui/icon-svg/icon-svg.stories.ts @@ -1,10 +1,10 @@ import { Meta, Story } from "@storybook/vue3"; -import IconSvg from "~/components/IconSvg/IconSvg.vue"; +import IconSvg from "./icon-svg.vue"; const iconNames = ((import.meta.env.STORYBOOK_ICON_SVG_NAMES as string) || '').split(','); export default { - title: "Components/IconSvg", + title: "Shared/IconSvg", component: IconSvg, argTypes: { name: { diff --git a/components/IconSvg/IconSvg.vue b/src/shared/ui/icon-svg/icon-svg.vue similarity index 95% rename from components/IconSvg/IconSvg.vue rename to src/shared/ui/icon-svg/icon-svg.vue index a247d8f9..5d4dcda0 100644 --- a/components/IconSvg/IconSvg.vue +++ b/src/shared/ui/icon-svg/icon-svg.vue @@ -1,3 +1,11 @@ + + - - diff --git a/src/shared/ui/sorting-wrapper/constants.ts b/src/shared/ui/sorting-wrapper/constants.ts new file mode 100644 index 00000000..4d95cb98 --- /dev/null +++ b/src/shared/ui/sorting-wrapper/constants.ts @@ -0,0 +1,6 @@ + +export enum SORTING_ORDER { + ASC = 'asc', + DESC = 'desc', + DEFAULT = 'default', +} diff --git a/src/shared/ui/sorting-wrapper/index.ts b/src/shared/ui/sorting-wrapper/index.ts new file mode 100644 index 00000000..8c1ef292 --- /dev/null +++ b/src/shared/ui/sorting-wrapper/index.ts @@ -0,0 +1,4 @@ +import { SORTING_ORDER } from "./constants"; +import SortingWrapper from "./sorting-wrapper.vue"; + +export { SortingWrapper, SORTING_ORDER }; diff --git a/components/SortWrap/SortWrap.stories.ts b/src/shared/ui/sorting-wrapper/sorting-wrapper.stories.ts similarity index 79% rename from components/SortWrap/SortWrap.stories.ts rename to src/shared/ui/sorting-wrapper/sorting-wrapper.stories.ts index 709f28ce..f3c41869 100644 --- a/components/SortWrap/SortWrap.stories.ts +++ b/src/shared/ui/sorting-wrapper/sorting-wrapper.stories.ts @@ -1,10 +1,10 @@ -import { Meta, Story } from "@storybook/vue3"; -import SortWrap from "~/components/SortWrap/SortWrap.vue"; -import { SORT_ORDER } from "~/config/constants"; import { action } from "@storybook/addon-actions"; +import { Meta, Story } from "@storybook/vue3"; +import { SORTING_ORDER } from "./constants"; +import SortWrap from "./sorting-wrapper.vue"; export default { - title: "Components/SortWrap", + title: "Shared/SortingWrapper", component: SortWrap, } as Meta; @@ -16,7 +16,7 @@ const Template: Story = (args) => ({ setup() { return { args, - SORT_ORDER, + SORTING_ORDER, }; }, @@ -33,7 +33,7 @@ const Template: Story = (args) => ({
ASC sort @@ -42,7 +42,7 @@ const Template: Story = (args) => ({
DESC sort diff --git a/src/shared/ui/sorting-wrapper/sorting-wrapper.vue b/src/shared/ui/sorting-wrapper/sorting-wrapper.vue new file mode 100644 index 00000000..176a730f --- /dev/null +++ b/src/shared/ui/sorting-wrapper/sorting-wrapper.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/src/shared/ui/stat-board/index.ts b/src/shared/ui/stat-board/index.ts new file mode 100644 index 00000000..5a7cc291 --- /dev/null +++ b/src/shared/ui/stat-board/index.ts @@ -0,0 +1,5 @@ +import StatBoard from "./stat-board.vue"; + +export { + StatBoard +} diff --git a/components/StatBoard/StatBoard.stories.ts b/src/shared/ui/stat-board/stat-board.stories.ts similarity index 55% rename from components/StatBoard/StatBoard.stories.ts rename to src/shared/ui/stat-board/stat-board.stories.ts index f513c67f..77149d64 100644 --- a/components/StatBoard/StatBoard.stories.ts +++ b/src/shared/ui/stat-board/stat-board.stories.ts @@ -1,11 +1,8 @@ import { Meta, Story } from "@storybook/vue3"; -import { normalizeProfilerEvent } from "~/utils/normalize-event"; -import StatBoard from "~/components/StatBoard/StatBoard.vue"; -import profilerEventMock from "~/mocks/profiler.json"; -import type { Profiler } from "~/config/types"; +import StatBoard from "./stat-board.vue"; export default { - title: "Components/StatBoard", + title: "Shared/StatBoard", component: StatBoard, } as Meta; @@ -16,13 +13,19 @@ const Template: Story = (args) => ({ args, }; }, - template: ``, + template: ``, }); export const Default = Template.bind({}); Default.args = { - cost: (normalizeProfilerEvent(profilerEventMock).payload as Profiler)?.peaks, + cost: { + ct: 1, + wt: 206270, + cpu: 44750, + mu: 3112176, + pmu: 3001416 +}, }; export const LargePeaks = Template.bind({}); diff --git a/src/shared/ui/stat-board/stat-board.vue b/src/shared/ui/stat-board/stat-board.vue new file mode 100644 index 00000000..e25d5670 --- /dev/null +++ b/src/shared/ui/stat-board/stat-board.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/shared/ui/table-base/index.ts b/src/shared/ui/table-base/index.ts new file mode 100644 index 00000000..02b36499 --- /dev/null +++ b/src/shared/ui/table-base/index.ts @@ -0,0 +1,9 @@ +// TODO: need to update concat table and row to single component + +import TableBaseRow from './table-base-row.vue'; +import TableBase from './table-base.vue'; + +export { + TableBase, + TableBaseRow, +} diff --git a/src/shared/ui/table-base/table-base-row.vue b/src/shared/ui/table-base/table-base-row.vue new file mode 100644 index 00000000..6d2b051b --- /dev/null +++ b/src/shared/ui/table-base/table-base-row.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/shared/ui/table-base/table-base.stories.ts b/src/shared/ui/table-base/table-base.stories.ts new file mode 100644 index 00000000..24ca3b45 --- /dev/null +++ b/src/shared/ui/table-base/table-base.stories.ts @@ -0,0 +1,65 @@ +import { Meta, Story } from "@storybook/vue3"; +import TableBaseRow from "./table-base-row.vue"; +import TableBase from "./table-base.vue"; + +export default { + title: "Shared/TableBase", + component: TableBase +} as Meta; + +const TableTemplate: Story = (args) => ({ + components: { TableBase, TableBaseRow }, + setup() { + return { + args, + }; + }, + template: ` + + This is a row 1 + + + This is a row 2 + + + This is a row 3 + + `, +}); + +export const Default = TableTemplate.bind({}); +Default.args = {}; + +const TableWithoutTitlesTemplate: Story = (args) => ({ + components: { TableBase, TableBaseRow }, + setup() { + return { + args, + }; + }, + template: ` + + This is a row 1 + + + This is a row 2 + + + This is a row 3 + + `, +}); +export const NoTitles = TableWithoutTitlesTemplate.bind({}); +NoTitles.args = {}; + +const RowOnlyTemplate: Story = (args) => ({ + components: { TableBase, TableBaseRow }, + setup() { + return { + args, + }; + }, + template: `This is a row 1`, +}); +export const RowOnly = RowOnlyTemplate.bind({}); +RowOnly.args = {}; diff --git a/components/EventTable/EventTable.vue b/src/shared/ui/table-base/table-base.vue similarity index 58% rename from components/EventTable/EventTable.vue rename to src/shared/ui/table-base/table-base.vue index 9293152c..8b8fac2f 100644 --- a/components/EventTable/EventTable.vue +++ b/src/shared/ui/table-base/table-base.vue @@ -1,19 +1,17 @@ + + - - + + diff --git a/src/shared/ui/value-dump/index.ts b/src/shared/ui/value-dump/index.ts new file mode 100644 index 00000000..fd6f9747 --- /dev/null +++ b/src/shared/ui/value-dump/index.ts @@ -0,0 +1,3 @@ +import ValueDump from './value-dump.vue'; + +export { ValueDump }; diff --git a/components/ValueDump/ValueDump.stories.ts b/src/shared/ui/value-dump/value-dump.stories.ts similarity index 55% rename from components/ValueDump/ValueDump.stories.ts rename to src/shared/ui/value-dump/value-dump.stories.ts index 9f99d7c4..339872e5 100644 --- a/components/ValueDump/ValueDump.stories.ts +++ b/src/shared/ui/value-dump/value-dump.stories.ts @@ -1,10 +1,9 @@ import { Meta, Story } from "@storybook/vue3"; - -import ValueDump from '~/components/ValueDump/ValueDump.vue'; -import varDumpObjectEventMock from '~/mocks/var-dump-object.json' +import { SFDumpCode, HTMLEscapedString } from "../../mocks"; +import ValueDump from './value-dump.vue'; export default { - title: "Components/ValueDump", + title: "Shared/ValueDump", component: ValueDump } as Meta; @@ -21,7 +20,7 @@ const Template: Story = (args) => ({ export const String = Template.bind({}); String.args = { - value: `<?xml version="1.0"?>
<one>
  <two>
    <three>3</three>
  </two>
</one>`, + value: HTMLEscapedString, type: 'string', }; @@ -34,5 +33,5 @@ Boolean.args = { export const SfDump = Template.bind({}); SfDump.args = { - value: varDumpObjectEventMock.payload.payload.value, + value: SFDumpCode, }; diff --git a/src/shared/ui/value-dump/value-dump.vue b/src/shared/ui/value-dump/value-dump.vue new file mode 100644 index 00000000..a3f8d080 --- /dev/null +++ b/src/shared/ui/value-dump/value-dump.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/components/PreviewEventMapper/PreviewEventMapper.stories.ts b/src/widgets/ui/event-card/event-card.stories.ts similarity index 51% rename from components/PreviewEventMapper/PreviewEventMapper.stories.ts rename to src/widgets/ui/event-card/event-card.stories.ts index b1d1adcd..21ca4e10 100644 --- a/components/PreviewEventMapper/PreviewEventMapper.stories.ts +++ b/src/widgets/ui/event-card/event-card.stories.ts @@ -1,104 +1,104 @@ import { Meta, Story } from "@storybook/vue3"; -import PreviewEventMapper from "~/components/PreviewEventMapper/PreviewEventMapper.vue"; -import monologEventMock from "~/mocks/monolog.json"; -import sentryEventMock from "~/mocks/sentry-spiral.json"; -import smtpEventMock from "~/mocks/smtp-welcome.json"; -import varDumpEventMock from "~/mocks/var-dump-object.json"; -import profilerEventMock from "~/mocks/profiler.json"; -import inspectorEventMock from "~/mocks/inspector.json"; -import httpDumpEventMock from "~/mocks/http-dump.json"; +import { httpDumpMock } from '~/src/entities/http-dump/mocks'; +import { inspectorMock } from '~/src/entities/inspector/mocks'; +import { monologMock } from '~/src/entities/monolog/mocks'; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import { sentrySpiralMock } from '~/src/entities/sentry/mocks'; +import { smtpWelcomeMock } from '~/src/entities/smtp/mocks'; +import { varDumpObjectMock } from "~/src/entities/var-dump/mocks"; +import PreviewCard from "./event-card.vue"; export default { - title: "Preview/PreviewEventMapper", - component: PreviewEventMapper, -} as Meta; + title: "Widgets/PreviewCard", + component: PreviewCard, +} as Meta; const Template: Story = (args) => ({ - components: { PreviewEventMapper }, + components: { PreviewCard }, setup() { return { args, }; }, - template: ``, + template: ``, }); export const Default = Template.bind({}); Default.args = { - event: { ...smtpEventMock, type: "unknown" }, + event: { ...smtpWelcomeMock, type: "unknown" }, }; export const Monolog = Template.bind({}); Monolog.args = { - event: monologEventMock, + event: monologMock, }; export const Sentry = Template.bind({}); Sentry.args = { - event: sentryEventMock, + event: sentrySpiralMock, }; export const Smtp = Template.bind({}); Smtp.args = { - event: smtpEventMock, + event: smtpWelcomeMock, }; export const VarDump = Template.bind({}); VarDump.args = { - event: varDumpEventMock, + event: varDumpObjectMock, }; export const Profiler = Template.bind({}); Profiler.args = { - event: profilerEventMock, + event: profilerMock, }; export const Inspector = Template.bind({}); Inspector.args = { - event: inspectorEventMock, + event: inspectorMock, }; export const HttpDump = Template.bind({}); HttpDump.args = { - event: httpDumpEventMock, + event: httpDumpMock, }; const eventsList = [ - monologEventMock, - sentryEventMock, - smtpEventMock, - varDumpEventMock, - profilerEventMock, - inspectorEventMock, - httpDumpEventMock, + monologMock, + sentrySpiralMock, + smtpWelcomeMock, + varDumpObjectMock, + profilerMock, + inspectorMock, + httpDumpMock, ]; const TemplateList: Story = (args) => ({ - components: { PreviewEventMapper }, + components: { PreviewCard }, setup() { return { args, eventsList, }; }, - template: ``, + template: ``, }); export const EventsList = TemplateList.bind({}); EventsList.args = { - event: inspectorEventMock, + event: inspectorMock, }; const TemplateListVirtual: Story = (args) => ({ - components: { PreviewEventMapper }, + components: { PreviewCard }, setup() { return { args, @@ -114,7 +114,7 @@ const TemplateListVirtual: Story = (args) => ({ }, template: ` `, }); @@ -122,5 +122,5 @@ const TemplateListVirtual: Story = (args) => ({ export const EventsListVirtual = TemplateListVirtual.bind({}); EventsListVirtual.args = { - event: inspectorEventMock, + event: inspectorMock, }; diff --git a/src/widgets/ui/event-card/event-card.vue b/src/widgets/ui/event-card/event-card.vue new file mode 100644 index 00000000..238a08aa --- /dev/null +++ b/src/widgets/ui/event-card/event-card.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/widgets/ui/event-card/index.ts b/src/widgets/ui/event-card/index.ts new file mode 100644 index 00000000..60328a0b --- /dev/null +++ b/src/widgets/ui/event-card/index.ts @@ -0,0 +1,3 @@ +import EventCard from './event-card.vue' + +export { EventCard }; diff --git a/src/widgets/ui/index.ts b/src/widgets/ui/index.ts new file mode 100644 index 00000000..0d3f1a6d --- /dev/null +++ b/src/widgets/ui/index.ts @@ -0,0 +1,6 @@ +export * from './render-graph'; +export * from './page-header'; +export * from './event-card'; +export * from './preview-card-default'; +export * from './page-placeholder'; +export * from './layout-sidebar'; diff --git a/src/widgets/ui/layout-sidebar/index.ts b/src/widgets/ui/layout-sidebar/index.ts new file mode 100644 index 00000000..5a30542a --- /dev/null +++ b/src/widgets/ui/layout-sidebar/index.ts @@ -0,0 +1 @@ +export { default as LayoutSidebar } from "./layout-sidebar.vue"; diff --git a/components/LayoutSidebar/LayoutSidebar.stories.ts b/src/widgets/ui/layout-sidebar/layout-sidebar.stories.ts similarity index 74% rename from components/LayoutSidebar/LayoutSidebar.stories.ts rename to src/widgets/ui/layout-sidebar/layout-sidebar.stories.ts index 44093dff..e420af67 100644 --- a/components/LayoutSidebar/LayoutSidebar.stories.ts +++ b/src/widgets/ui/layout-sidebar/layout-sidebar.stories.ts @@ -1,8 +1,8 @@ import { Meta, Story } from "@storybook/vue3"; -import LayoutSidebar from "~/components/LayoutSidebar/LayoutSidebar.vue"; +import LayoutSidebar from "./layout-sidebar.vue"; export default { - title: "Components/LayoutSidebar", + title: "Widgets/LayoutSidebar", component: LayoutSidebar }as Meta; @@ -18,5 +18,6 @@ const Template: Story = (args) => ({ export const Default = Template.bind({}); Default.args = { - isConnected: true, + apiVersion: "v1.0.0", + clientVersion: "v1.0.0", }; diff --git a/components/LayoutSidebar/LayoutSidebar.vue b/src/widgets/ui/layout-sidebar/layout-sidebar.vue similarity index 81% rename from components/LayoutSidebar/LayoutSidebar.vue rename to src/widgets/ui/layout-sidebar/layout-sidebar.vue index 54f96955..83ba2953 100644 --- a/components/LayoutSidebar/LayoutSidebar.vue +++ b/src/widgets/ui/layout-sidebar/layout-sidebar.vue @@ -1,3 +1,28 @@ + + - - diff --git a/components/PagePlaceholder/PagePlaceholder.stories.ts b/src/widgets/ui/page-placeholder/page-placeholder.stories.ts similarity index 75% rename from components/PagePlaceholder/PagePlaceholder.stories.ts rename to src/widgets/ui/page-placeholder/page-placeholder.stories.ts index 6f1a1464..4bfa88da 100644 --- a/components/PagePlaceholder/PagePlaceholder.stories.ts +++ b/src/widgets/ui/page-placeholder/page-placeholder.stories.ts @@ -1,8 +1,8 @@ import { Meta, Story } from "@storybook/vue3"; -import PagePlaceholder from "~/components/PagePlaceholder/PagePlaceholder.vue"; +import PagePlaceholder from "./page-placeholder.vue"; export default { - title: "Components/PagePlaceholder", + title: "Widgets/PagePlaceholder", component: PagePlaceholder }as Meta; diff --git a/src/widgets/ui/page-placeholder/page-placeholder.vue b/src/widgets/ui/page-placeholder/page-placeholder.vue new file mode 100644 index 00000000..70307b99 --- /dev/null +++ b/src/widgets/ui/page-placeholder/page-placeholder.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/widgets/ui/preview-card-default/index.ts b/src/widgets/ui/preview-card-default/index.ts new file mode 100644 index 00000000..04b8a77b --- /dev/null +++ b/src/widgets/ui/preview-card-default/index.ts @@ -0,0 +1 @@ +export { default as PreviewCardDefault } from './preview-card-default.vue' diff --git a/src/widgets/ui/preview-card-default/preview-card-default.ts b/src/widgets/ui/preview-card-default/preview-card-default.ts new file mode 100644 index 00000000..38ae4300 --- /dev/null +++ b/src/widgets/ui/preview-card-default/preview-card-default.ts @@ -0,0 +1,27 @@ +import { Meta, Story } from "@storybook/vue3"; +import { monologMock } from '~/src/entities/monolog/mocks' +import { useEvents } from "~/src/shared/lib/use-events"; +import PreviewCardDefault from './preview-card-default.vue'; + +const { normalizeUnknownEvent } = useEvents(); + +export default { + title: "Widgets/PreviewCardDefault", + component: PreviewCardDefault +} as Meta; + +const Template: Story = (args) => ({ + components: { PreviewCardDefault }, + setup() { + return { + args, + }; + }, + template: ``, +}); + +export const Default = Template.bind({}); + +Default.args = { + event: normalizeUnknownEvent({ ...monologMock, type: 'unknown' }), +}; diff --git a/src/widgets/ui/preview-card-default/preview-card-default.vue b/src/widgets/ui/preview-card-default/preview-card-default.vue new file mode 100644 index 00000000..ea56034d --- /dev/null +++ b/src/widgets/ui/preview-card-default/preview-card-default.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/src/widgets/ui/render-graph/index.ts b/src/widgets/ui/render-graph/index.ts new file mode 100644 index 00000000..7485fd90 --- /dev/null +++ b/src/widgets/ui/render-graph/index.ts @@ -0,0 +1,2 @@ +export { default as RenderGraph } from './render-graph.vue'; +export { useRenderGraph } from './use-render-graph'; diff --git a/components/RenderGraph/RenderGraph.stories.ts b/src/widgets/ui/render-graph/render-graph.stories.ts similarity index 74% rename from components/RenderGraph/RenderGraph.stories.ts rename to src/widgets/ui/render-graph/render-graph.stories.ts index 31d4abf4..b00dad9c 100644 --- a/components/RenderGraph/RenderGraph.stories.ts +++ b/src/widgets/ui/render-graph/render-graph.stories.ts @@ -1,11 +1,12 @@ import { Meta, Story } from "@storybook/vue3"; -import RenderGraph from '~/components/RenderGraph/RenderGraph.vue'; -import profilerEventMock from '~/mocks/profiler.json' -import { GraphTypes } from "~/config/types"; -import { calcGraphData } from "~/utils/calc-graph-data"; +import { profilerMock } from "~/src/entities/profiler/mocks"; +import { GraphTypes } from "~/src/shared/types"; +import RenderGraph from './render-graph.vue'; +import { useRenderGraph } from "./use-render-graph"; +const { prepare } = useRenderGraph(); export default { - title: "Components/RenderGraph", + title: "Widgets/RenderGraph", component: RenderGraph } as Meta; @@ -16,7 +17,7 @@ const Template: Story = (args) => ({ args, }; }, - template: ``, + template: ``, }); export const TestData = Template.bind({}); @@ -48,17 +49,17 @@ TestData.args = { export const ProfilerData = Template.bind({}); ProfilerData.args = { - elements: calcGraphData(profilerEventMock.payload.edges, GraphTypes.CPU, 1) + elements: prepare(profilerMock.payload.edges, GraphTypes.CPU, 1, 10) }; export const ProfilerMemoryData = Template.bind({}); ProfilerMemoryData.args = { - elements: calcGraphData(profilerEventMock.payload.edges, GraphTypes.MEMORY, 1) + elements: prepare(profilerMock.payload.edges, GraphTypes.MEMORY, 1, 10) }; export const ProfilerMemoryChangeData = Template.bind({}); ProfilerMemoryChangeData.args = { - elements: calcGraphData(profilerEventMock.payload.edges, GraphTypes.MEMORY_CHANGE, 1) + elements: prepare(profilerMock.payload.edges, GraphTypes.MEMORY_CHANGE, 1, 10) }; diff --git a/src/widgets/ui/render-graph/render-graph.vue b/src/widgets/ui/render-graph/render-graph.vue new file mode 100644 index 00000000..bd2d2da3 --- /dev/null +++ b/src/widgets/ui/render-graph/render-graph.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/widgets/ui/render-graph/use-render-graph.ts b/src/widgets/ui/render-graph/use-render-graph.ts new file mode 100644 index 00000000..abbd7fcd --- /dev/null +++ b/src/widgets/ui/render-graph/use-render-graph.ts @@ -0,0 +1,8 @@ +import { useCytoscape } from "~/src/features/lib/cytoscape"; + +const { buildData, initialize } = useCytoscape(); + +export const useRenderGraph = () => ({ + prepare: buildData, + initialize, +}) diff --git a/stores/cached-ids.ts b/stores/cached-ids.ts index cde19c3f..f2c44b2d 100644 --- a/stores/cached-ids.ts +++ b/stores/cached-ids.ts @@ -1,20 +1,21 @@ import { defineStore } from "pinia"; -import { EventId, TEventGroup, TEventType } from "~/config/types"; -import { ALL_EVENTS, EVENT_TYPES, LOCAL_STORAGE_KEYS } from "~/config/constants"; +import { EventId, LOCAL_STORAGE_KEYS, OneOfValues } from '~/src/shared/types'; +import { PAGE_TYPES } from "~/src/shared/constants"; import { useEventStore } from "~/stores/events"; +type TEventsGroup = OneOfValues -type TCachedEventsEmptyMap = Record; +type TCachedEventsEmptyMap = Record; -const initialcachedIds: TCachedEventsEmptyMap = { - [EVENT_TYPES.SENTRY]: [] as EventId[], - [EVENT_TYPES.INSPECTOR]: [] as EventId[], - [EVENT_TYPES.PROFILER]: [] as EventId[], - [EVENT_TYPES.SMTP]: [] as EventId[], - [EVENT_TYPES.RAY_DUMP]: [] as EventId[], - [EVENT_TYPES.VAR_DUMP]: [] as EventId[], - [EVENT_TYPES.HTTP_DUMP]: [] as EventId[], - [ALL_EVENTS]: [] as EventId[], +const initialCachedIds: TCachedEventsEmptyMap = { + [PAGE_TYPES.SENTRY]: [] as EventId[], + [PAGE_TYPES.INSPECTOR]: [] as EventId[], + [PAGE_TYPES.PROFILER]: [] as EventId[], + [PAGE_TYPES.SMTP]: [] as EventId[], + [PAGE_TYPES.RAY_DUMP]: [] as EventId[], + [PAGE_TYPES.VAR_DUMP]: [] as EventId[], + [PAGE_TYPES.HTTP_DUMP]: [] as EventId[], + [PAGE_TYPES.ALL_EVENTS]: [] as EventId[], }; const { localStorage } = window; @@ -25,7 +26,7 @@ const getCachedIds = (): TCachedEventsEmptyMap => { return JSON.parse(storageValue) as TCachedEventsEmptyMap; } - return initialcachedIds; + return initialCachedIds; }; const syncLocalStorage = (cachedEventMap: TCachedEventsEmptyMap) => { @@ -38,16 +39,16 @@ export const useCachedIdsStore = defineStore("useCachedIdsStore", { }), getters: { cachedTypesList(state) { - return Object.entries(state.cachedIds).filter(([_, value]) => value.length > 0).map(([key]) => key) + return Object.entries(state.cachedIds).filter(([_, value]) => value.length > 0).map(([key]) => key as TEventsGroup) } }, actions: { - setByType(cachedType: TEventGroup) { + setByType(cachedType: TEventsGroup) { const { events } = useEventStore(); events .filter(({ type }) => - type === cachedType || cachedType === ALL_EVENTS + type === cachedType || cachedType === PAGE_TYPES.ALL_EVENTS ) .forEach((event) => { this.cachedIds[cachedType].push(event.uuid); @@ -55,7 +56,7 @@ export const useCachedIdsStore = defineStore("useCachedIdsStore", { syncLocalStorage(this.cachedIds); }, - removeByType(type: TEventGroup) { + removeByType(type: TEventsGroup) { this.cachedIds[type].length = 0; syncLocalStorage(this.cachedIds); }, @@ -69,7 +70,7 @@ export const useCachedIdsStore = defineStore("useCachedIdsStore", { syncLocalStorage(this.cachedIds); }, removeAll() { - this.cachedIds = initialcachedIds; + this.cachedIds = initialCachedIds; syncLocalStorage(this.cachedIds); }, syncWithActive(activeIds: EventId[]) { diff --git a/stores/events.ts b/stores/events.ts index 4c54638d..9164fb25 100644 --- a/stores/events.ts +++ b/stores/events.ts @@ -1,5 +1,5 @@ import { defineStore } from "pinia"; -import { EventId, ServerEvent, TEventType } from "~/config/types"; +import { EventId, EventType, ServerEvent } from '~/src/shared/types'; export const useEventStore = defineStore("useEventStore", { state: () => ({ @@ -28,7 +28,7 @@ export const useEventStore = defineStore("useEventStore", { removeById(eventUuid: EventId) { this.events = this.events.filter(({ uuid }) => uuid !== eventUuid); }, - removeByType(eventType: TEventType) { + removeByType(eventType: EventType) { this.events = this.events.filter(({ type }) => type !== eventType); }, diff --git a/stores/settings.ts b/stores/settings.ts index a774b53b..f23221a5 100644 --- a/stores/settings.ts +++ b/stores/settings.ts @@ -1,5 +1,5 @@ import { defineStore } from "pinia"; -import { LOCAL_STORAGE_KEYS } from "~/config/constants"; +import { LOCAL_STORAGE_KEYS } from "~/src/shared/types"; export const THEME_MODES = { LIGHT: "light", diff --git a/utils/flamegraph-builder.ts b/utils/flamegraph-builder.ts deleted file mode 100644 index 9f37d940..00000000 --- a/utils/flamegraph-builder.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { ProfilerCost, ProfilerEdges } from "~/config/types"; -import {FlameChartNode} from "flame-chart-js/dist/types"; - -type FlameChartData = FlameChartNode & { - cost: ProfilerCost -} - -export default class { - private walked: string[] = [] - - private readonly edges: ProfilerEdges - - constructor(edges: ProfilerEdges) { - this.edges = edges - } - - build(field = 'cpu'): FlameChartData { - this.walked = [] - - const datum: Record = {} - - Object.values(this.edges).forEach((edge) => { - const parent = edge.caller - const target = edge.callee - - const duration = (edge.cost[field] || 0) > 0 ? edge.cost[field] / 1_000 : 0 - const start = 0 - - if (target && !datum[target]) { - datum[target] = { - name: target, - start, - duration, - cost: edge.cost, - children: [] - } - } - - if (parent && !datum[parent]) { - datum[parent] = { - name: parent, - start, - duration, - cost: edge.cost, - children: [] - } - } - - // NOTE: walked skips several targettions (recursion detected), should be fixed - if (!parent || this.walked.includes(target)) { - // console.log(node, target) - return - } - - if (datum[parent] && datum[parent].children) { - const parentChildren = datum[parent].children || [] - - const lastChild = parentChildren ? parentChildren[parentChildren.length - 1]: null - datum[target].start = lastChild ? lastChild.start + lastChild.duration : datum[target].start - } else { - datum[target].start += datum[parent].start - } - - datum[parent].children?.push(datum[target]) - this.walked.push(target) - }) - - this.walked = [] - - return datum['main()'] - } -} diff --git a/utils/formats.test.ts b/utils/formats.test.ts deleted file mode 100644 index 5d7ba1a7..00000000 --- a/utils/formats.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { expect, test, describe } from "vitest"; -import { formatDuration } from "./formats"; - -describe("formatDuration", () => { - test("should return correct string for milliseconds", () => { - expect(formatDuration(1)).toBe("0.0010 ms"); - expect(formatDuration(1000)).toBe("1 ms"); - }); - - test("should return correct string for milliseconds negative", () => { - expect(formatDuration(-1)).toBe("0.0010 ms"); - expect(formatDuration(-1000)).toBe("1 ms"); - }); - - test("should return correct string for seconds", () => { - expect(formatDuration(1000 * 1000)).toBe("1 s"); - expect(formatDuration(1000 * 1000 * 59.9999)).toBe("59 s, 999.9000 ms"); - }); - - test("should return correct string for minutes", () => { - expect(formatDuration(1000 * 1000 * 60)).toBe("1 m"); - expect(formatDuration(1000 * 1000 * 60 * 59.9999)).toBe("59 m, 59 s, 994 ms"); - }); - - test("should return correct string for hours", () => { - expect(formatDuration(1000 * 1000 * 60 * 60)).toBe("1 h"); - expect(formatDuration(1000 * 1000 * 60 * 60 * 23.9999)).toBe("23 h, 59 m, 59 s, 640 ms"); - }); - - test("should return correct string for days", () => { - expect(formatDuration(1000 * 1000 * 60 * 60 * 24)).toBe("1 d"); - expect(formatDuration(1000 * 1000 * 60 * 60 * 24 * 364.9999)).toBe("364 d, 23 h, 59 m, 51 s, 360 ms"); - }); -}); diff --git a/utils/normalize-event.ts b/utils/normalize-event.ts deleted file mode 100644 index 2a3f24fd..00000000 --- a/utils/normalize-event.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - HttpDump, - Inspector, - InspectorTransaction, - Monolog, - NormalizedEvent, - Profiler, - RayDump, - Sentry, - ServerEvent, - SMTP, - VarDump -} from "~/config/types"; -import {EVENT_TYPES, RAY_EVENT_TYPES} from "~/config/constants"; - -import {pick} from "lodash"; - -const normalizeObjectValue = (object: object | unknown[]): object => - Object.entries(object).reduce((acc: object, [key, value]) => ({ - ...acc, - [key]: value - }), {}) - -export const normalizeFallbackEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: 'unknown', - labels: [event.type], - origin: null, - serverName: "", - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - -export const normalizeInspectorEvent = (event: ServerEvent): NormalizedEvent => { - const transaction = event.payload[0] as InspectorTransaction; - - return { - id: event.uuid, - type: EVENT_TYPES.INSPECTOR, - labels: [EVENT_TYPES.INSPECTOR], - origin: {name: transaction.host.hostname, ip: transaction.host.ip, os: transaction.host.os}, - serverName: transaction.host.hostname, - date: new Date(event.timestamp * 1000), - payload: event.payload - } -} - -export const normalizeProfilerEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.PROFILER, - labels: [EVENT_TYPES.PROFILER], - origin: {name: event.payload.app_name, ...event.payload.tags}, - serverName: event.payload.hostname, - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - -export const normalizeHttpDumpEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.HTTP_DUMP, - labels: [EVENT_TYPES.HTTP_DUMP], - origin: {uri: event.payload.request.uri}, - serverName: event.payload.host, - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - - -export const normalizeMonologEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.MONOLOG, - labels: [EVENT_TYPES.MONOLOG, event.payload.level_name], - origin: null, - serverName: event.payload.channel, - date: new Date(event.timestamp * 1000), - payload: { - ...event.payload, - context: normalizeObjectValue(event.payload.context), - extra: normalizeObjectValue(event.payload.extra) - } -}) - -export const normalizeSentryEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.SENTRY, - labels: [EVENT_TYPES.SENTRY, 'exception'], - origin: { - logger: event.payload.logger, - environment: event.payload.environment - }, - serverName: event.payload.server_name, - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - -export const normalizeSMTPEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.SMTP, - labels: [EVENT_TYPES.SMTP], - origin: null, - serverName: "", - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - -export const normalizeVarDumpEvent = (event: ServerEvent): NormalizedEvent => ({ - id: event.uuid, - type: EVENT_TYPES.VAR_DUMP, - labels: [EVENT_TYPES.VAR_DUMP], - origin: { - file: event.payload.context.source.file, - name: event.payload.context.source.name, - line_number: event.payload.context.source.line, - }, - serverName: "", - date: new Date(event.timestamp * 1000), - payload: event.payload -}) - -export const normalizeRayDumpEvent = (event: ServerEvent): NormalizedEvent => { - let origin = { - php_version: event.payload.meta?.php_version, - laravel_version: event.payload.meta?.laravel_version, - } - - event.payload.payloads - .forEach(payload => { - if (payload.hasOwnProperty('origin')) { - origin = { - ...origin, - ...pick(payload.origin, ['file', 'line_number', 'hostname']), - } - } - }) - - const labels = event.payload.payloads - .filter(payload => payload.type === 'label') - .map(payload => payload.content.label) - - const typeLabels = event.payload.payloads - .filter(payload => Object.values(RAY_EVENT_TYPES).includes(payload.type)) - .map(payload => payload.type) - - event.payload.payloads - .filter(payload => payload.type === 'size') - - const color = event.payload.payloads - .filter(payload => payload.type === 'color') - .map(payload => payload.content.color).shift() || 'black' - - const size = event.payload.payloads - .filter(payload => payload.type === 'size') - .map(payload => payload.content.size).shift() || 'md' - - return { - id: event.uuid, - type: EVENT_TYPES.RAY_DUMP, - labels: [EVENT_TYPES.RAY_DUMP, ...labels, ...typeLabels].filter((x, i, a) => a.indexOf(x) === i), - origin: origin, - serverName: "", - date: new Date(event.timestamp * 1000), - color, - size, - payload: event - } -} - diff --git a/vendor/dumper.js b/vendor/dumper.js deleted file mode 100644 index 6d95b7ee..00000000 --- a/vendor/dumper.js +++ /dev/null @@ -1,403 +0,0 @@ -export default function (doc) { - let refStyle = doc.createElement('style'), rxEsc = /([.*+?^${}()|\[\]\/\\])/g, idRx = /\bsf-dump-\d+-ref[012]\w+\b/, - keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', - addEventListener = function (e, n, cb) { - e.addEventListener(n, cb, false); - }; - refStyle.innerHTML = 'pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }'; - (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); - refStyle = doc.createElement('style'); - (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); - if (!doc.addEventListener) { - addEventListener = function (element, eventName, callback) { - element.attachEvent('on' + eventName, function (e) { - e.preventDefault = function () { - e.returnValue = false; - }; - e.target = e.srcElement; - callback(e); - }); - }; - } - - function toggle(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; - if (/\bsf-dump-compact\b/.test(oldClass)) { - arrow = '▼'; - newClass = 'sf-dump-expanded'; - } else if (/\bsf-dump-expanded\b/.test(oldClass)) { - arrow = '▶'; - newClass = 'sf-dump-compact'; - } else { - return false; - } - if (doc.createEvent && s.dispatchEvent) { - var event = doc.createEvent('Event'); - event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); - s.dispatchEvent(event); - } - a.lastChild.innerHTML = arrow; - s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); - if (recursive) { - try { - a = s.querySelectorAll('.' + oldClass); - for (s = 0; s < a.length; ++s) { - if (-1 == a[s].className.indexOf(newClass)) { - a[s].className = newClass; - a[s].previousSibling.lastChild.innerHTML = arrow; - } - } - } catch (e) { - } - } - return true; - }; - - function collapse(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className; - if (/\bsf-dump-expanded\b/.test(oldClass)) { - toggle(a, recursive); - return true; - } - return false; - }; - - function expand(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className; - if (/\bsf-dump-compact\b/.test(oldClass)) { - toggle(a, recursive); - return true; - } - return false; - }; - - function collapseAll(root) { - var a = root.querySelector('a.sf-dump-toggle'); - if (a) { - collapse(a, true); - expand(a); - return true; - } - return false; - } - - function reveal(node) { - var previous, parents = []; - while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { - parents.push(previous); - } - if (0 !== parents.length) { - parents.forEach(function (parent) { - expand(parent); - }); - return true; - } - return false; - } - - function highlight(root, activeNode, nodes) { - resetHighlightedNodes(root); - Array.from(nodes || []).forEach(function (node) { - if (!/\bsf-dump-highlight\b/.test(node.className)) { - node.className = node.className + ' sf-dump-highlight'; - } - }); - if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { - activeNode.className = activeNode.className + ' sf-dump-highlight-active'; - } - } - - function resetHighlightedNodes(root) { - Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { - strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); - strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); - }); - } - - return function (root, x) { - root = doc.getElementById(root); - var indentRx = new RegExp('^(' + (root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1') + ')+', 'm'), - options = {"maxDepth": 1, "maxStringLength": 160, "fileLinkFormat": false}, - elt = root.getElementsByTagName('A'), len = elt.length, i = 0, s, h, t = []; - while (i < len) t.push(elt[i++]); - for (i in x) { - options[i] = x[i]; - } - - function a(e, f) { - addEventListener(root, e, function (e, n) { - if ('A' == e.target.tagName) { - f(e.target, e); - } else if ('A' == e.target.parentNode.tagName) { - f(e.target.parentNode, e); - } else { - n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; - if ((n = n.nextElementSibling) && 'A' == n.tagName) { - if (!/\bsf-dump-toggle\b/.test(n.className)) { - n = n.nextElementSibling || n; - } - f(n, e, true); - } - } - }); - }; - - function isCtrlKey(e) { - return e.ctrlKey || e.metaKey; - } - - function xpathString(str) { - var parts = str.match(/[^'"]+|['"]/g).map(function (part) { - if ("'" == part) { - return '"\'"'; - } - if ('"' == part) { - return "'\"'"; - } - return "'" + part + "'"; - }); - return "concat(" + parts.join(",") + ", '')"; - } - - function xpathHasClass(className) { - return "contains(concat(' ', normalize-space(@class), ' '), ' " + className + " ')"; - } - - addEventListener(root, 'mouseover', function (e) { - if ('' != refStyle.innerHTML) { - refStyle.innerHTML = ''; - } - }); - a('mouseover', function (a, e, c) { - if (c) { - e.target.style.cursor = "pointer"; - } else if (a = idRx.exec(a.className)) { - try { - refStyle.innerHTML = 'pre.sf-dump .' + a[0] + '{background-color: #B729D9; color: #FFF !important; border-radius: 2px}'; - } catch (e) { - } - } - }); - a('click', function (a, e, c) { - if (/\bsf-dump-toggle\b/.test(a.className)) { - e.preventDefault(); - if (!toggle(a, isCtrlKey(e))) { - var r = doc.getElementById(a.getAttribute('href').substr(1)), s = r.previousSibling, - f = r.parentNode, t = a.parentNode; - t.replaceChild(r, a); - f.replaceChild(a, s); - t.insertBefore(s, r); - f = f.firstChild.nodeValue.match(indentRx); - t = t.firstChild.nodeValue.match(indentRx); - if (f && t && f[0] !== t[0]) { - r.innerHTML = r.innerHTML.replace(new RegExp('^' + f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); - } - if (/\bsf-dump-compact\b/.test(r.className)) { - toggle(s, isCtrlKey(e)); - } - } - if (c) { - } else if (doc.getSelection) { - try { - doc.getSelection().removeAllRanges(); - } catch (e) { - doc.getSelection().empty(); - } - } else { - doc.selection.empty(); - } - } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { - e.preventDefault(); - e = a.parentNode.parentNode; - e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); - } - }); - elt = root.getElementsByTagName('SAMP'); - len = elt.length; - i = 0; - while (i < len) t.push(elt[i++]); - len = t.length; - for (i = 0; i < len; ++i) { - elt = t[i]; - if ('SAMP' == elt.tagName) { - a = elt.previousSibling || {}; - if ('A' != a.tagName) { - a = doc.createElement('A'); - a.className = 'sf-dump-ref'; - elt.parentNode.insertBefore(a, elt); - } else { - a.innerHTML += ' '; - } - a.title = (a.title ? a.title + '\n[' : '[') + keyHint + '+click] Expand all children'; - a.innerHTML += elt.className == 'sf-dump-compact' ? '' : ''; - a.className += ' sf-dump-toggle'; - x = 1; - if ('sf-dump' != elt.parentNode.className) { - x += elt.parentNode.getAttribute('data-depth') / 1; - } - } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { - a = a.substr(1); - elt.className += ' ' + a; - if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { - a = a != elt.nextSibling.id && doc.getElementById(a); - try { - s = a.nextSibling; - elt.appendChild(a); - s.parentNode.insertBefore(a, s); - if (/^[@#]/.test(elt.innerHTML)) { - elt.innerHTML += ' '; - } else { - elt.innerHTML = ''; - elt.className = 'sf-dump-ref'; - } - elt.className += ' sf-dump-toggle'; - } catch (e) { - if ('&' == elt.innerHTML.charAt(0)) { - elt.innerHTML = '…'; - elt.className = 'sf-dump-ref'; - } - } - } - } - } - if (doc.evaluate && Array.from && root.children.length > 1) { - root.setAttribute('tabindex', 0); - var SearchState = function () { - this.nodes = []; - this.idx = 0; - }; - SearchState.prototype = { - next: function () { - if (this.isEmpty()) { - return this.current(); - } - this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; - return this.current(); - }, previous: function () { - if (this.isEmpty()) { - return this.current(); - } - this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); - return this.current(); - }, isEmpty: function () { - return 0 === this.count(); - }, current: function () { - if (this.isEmpty()) { - return null; - } - return this.nodes[this.idx]; - }, reset: function () { - this.nodes = []; - this.idx = 0; - }, count: function () { - return this.nodes.length; - }, - }; - - function showCurrent(state) { - var currentNode = state.current(), currentRect, searchRect; - if (currentNode) { - reveal(currentNode); - highlight(root, currentNode, state.nodes); - if ('scrollIntoView' in currentNode) { - currentNode.scrollIntoView(true); - currentRect = currentNode.getBoundingClientRect(); - searchRect = search.getBoundingClientRect(); - if (currentRect.top < (searchRect.top + searchRect.height)) { - window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); - } - } - } - counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count(); - } - - var search = doc.createElement('div'); - search.className = 'sf-dump-search-wrapper sf-dump-search-hidden'; - search.innerHTML = ' 0 of 0<\/span>