Skip to content

Commit

Permalink
Merge pull request #49 from yiisoft/events
Browse files Browse the repository at this point in the history
Event listeners
  • Loading branch information
xepozz authored Jun 4, 2023
2 parents dfa1658 + 394c77b commit 05a2084
Show file tree
Hide file tree
Showing 25 changed files with 779 additions and 387 deletions.
9 changes: 8 additions & 1 deletion packages/yii-dev-panel-sdk/src/API/Debug/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {useSelector} from 'react-redux';

type StateType = {
entry: DebugEntry;
currentPageRequestIds: string[];
};
const initialState: StateType = {
entry: null,
currentPageRequestIds: [],
};
export const debugSlice = createSlice({
name: 'store.debug',
Expand All @@ -15,10 +17,15 @@ export const debugSlice = createSlice({
changeEntryAction: (state, action) => {
state.entry = action.payload;
},
addCurrentPageRequestId: (state, action) => {
state.currentPageRequestIds = [...state.currentPageRequestIds, action.payload].slice(0, 100);
},
},
});

export const {changeEntryAction} = debugSlice.actions;
export const {changeEntryAction, addCurrentPageRequestId} = debugSlice.actions;

type State = {[debugSlice.name]: ReturnType<typeof debugSlice.getInitialState>};
export const useDebugEntry = (): DebugEntry | null => useSelector((state: State) => state[debugSlice.name]?.entry);
export const useCurrentPageRequestIds = (): string[] =>
useSelector((state: State) => state[debugSlice.name]?.currentPageRequestIds);
3 changes: 2 additions & 1 deletion packages/yii-dev-panel-sdk/src/API/Debug/Debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,14 @@ type CollectorResponseType = any;

export const debugApi = createApi({
reducerPath: 'api.debug',
tagTypes: ['debug/list'],
baseQuery: createBaseQuery('/debug/api/'),
endpoints: (builder) => ({
getDebug: builder.query<DebugEntry[], void>({
query: () => ``,
transformResponse: (result: SummaryResponseType) => (result.data as DebugEntry[]) || [],
providesTags: ['debug/list'],
}),

getObject: builder.query<DebugEntry[], GetObjectProps>({
query: (args) => `object/${args.debugEntryId}/${args.objectId}`,
transformResponse: (result: SummaryResponseType) => (result.data as DebugEntry[]) || [],
Expand Down
1 change: 1 addition & 0 deletions packages/yii-dev-panel-sdk/src/API/Debug/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import storage from 'redux-persist/lib/storage';
const debugSliceConfig = {
key: debugSlice.reducer.name,
version: 1,
whitelist: ['entry'],
storage,
};

Expand Down
2 changes: 1 addition & 1 deletion packages/yii-dev-panel-sdk/src/API/createBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const createBaseQuery = (
const baseUrl = (WebApi.getState() as any).application?.baseUrl || '';

const rawBaseQuery = fetchBaseQuery({
baseUrl: baseUrl + baseUrlAdditional,
baseUrl: baseUrl.replace(/\/$/, '') + baseUrlAdditional,
referrerPolicy: 'no-referrer',
headers: {
Accept: 'application/json',
Expand Down
30 changes: 30 additions & 0 deletions packages/yii-dev-panel-sdk/src/Component/DebugChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import TerminalIcon from '@mui/icons-material/Terminal';
import {Chip} from '@mui/material';
import {DebugEntry} from '@yiisoft/yii-dev-panel-sdk/API/Debug/Debug';
import {buttonColorConsole, buttonColorHttp} from '@yiisoft/yii-dev-panel-sdk/Helper/buttonColor';
import {isDebugEntryAboutConsole, isDebugEntryAboutWeb} from '@yiisoft/yii-dev-panel-sdk/Helper/debugEntry';
type DebugChipProps = {
entry: DebugEntry;
};
export const DebugChip = ({entry}: DebugChipProps) => {
if (isDebugEntryAboutConsole(entry)) {
return (
<Chip
sx={{borderRadius: '5px 5px', margin: '0 2px'}}
icon={<TerminalIcon />}
label={entry.command?.exitCode}
color={buttonColorConsole(Number(entry.command?.exitCode))}
/>
);
}
if (isDebugEntryAboutWeb(entry)) {
return (
<Chip
sx={{borderRadius: '5px 5px', margin: '0 2px'}}
label={[entry.response?.statusCode, entry.request.method].join(' ')}
color={buttonColorHttp(entry.response?.statusCode)}
/>
);
}
return null;
};
14 changes: 14 additions & 0 deletions packages/yii-dev-panel-sdk/src/Helper/buttonColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {AlertColor} from '@mui/material';

export const buttonColorConsole = (code: number): AlertColor => (code === 0 ? 'success' : 'error');
export const buttonColorHttp = (status: number): AlertColor => {
switch (true) {
case status >= 400:
return 'error';
case status >= 300:
return 'warning';
case status >= 200:
return 'success';
}
return 'info';
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const serializeCallable = (raw: any): string => {
switch (true) {
case Array.isArray(raw) && raw.length === 2:
return raw.join('::');
return raw.join('::') + '()';
case typeof raw === 'string':
return raw;
default:
Expand Down
1 change: 1 addition & 0 deletions packages/yii-dev-panel-sdk/src/Pages/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const pages = [
link: '#',
items: [
{name: 'Routes', link: '/inspector/routes'},
{name: 'Events', link: '/inspector/events'},
{name: 'Parameters', link: '/inspector/parameters'},
{name: 'Configuration', link: '/inspector/configuration'},
{name: 'Container', link: '/inspector/container'},
Expand Down
154 changes: 154 additions & 0 deletions packages/yii-dev-panel-sdk/src/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/* eslint-disable no-restricted-globals */

// This service worker can be customized!
// See https://developers.google.com/web/tools/workbox/modules
// for the list of available Workbox modules, or add any other
// code you'd like.
// You can also remove this file if you'd prefer not to use a
// service worker, and the Workbox build step will be skipped.

import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {clientsClaim} from 'workbox-core';
import {ExpirationPlugin} from 'workbox-expiration';
import {createHandlerBoundToURL, precacheAndRoute} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

clientsClaim();

/**
* We are not wrapping it in a 'message' event as per the new update.
* @see https://developers.google.com/web/tools/workbox/modules/workbox-core
*/
self.skipWaiting();

// Precache all of the assets generated by your build process.
// Their URLs are injected into the manifest variable below.
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA
precacheAndRoute(self.__WB_MANIFEST);

// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
// @see https://developers.google.com/web/tools/workbox/guides/common-recipes#google_fonts
registerRoute(
({url}) => url.origin === 'https://fonts.googleapis.com',
new StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
}),
);

// Cache the underlying font files with a cache-first strategy for 1 year.
// @see https://developers.google.com/web/tools/workbox/guides/common-recipes#google_fonts
registerRoute(
({url}) => url.origin === 'https://fonts.gstatic.com',
new StaleWhileRevalidate({
cacheName: 'google-fonts-webfonts',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
],
}),
);
// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({request, url}) => {
// If this isn't a navigation, skip.
if (request.mode !== 'navigate') {
return false;
}

// If this is a URL that starts with /_, skip.
if (url.pathname.startsWith('/_')) {
return false;
}

// If this looks like a URL for a resource, because it contains // a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
return false;
}

// Return true to signal that we want to use the handler.
return true;
},
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html'),
);

registerRoute(
// Add in any other file extensions or routing criteria as needed.
({url}) =>
url.pathname.endsWith('.ico') ||
url.pathname.endsWith('.svg') ||
url.pathname.endsWith('.png') ||
url.pathname.endsWith('.jpeg') ||
url.pathname.endsWith('.jpg') ||
url.pathname.endsWith('.webp'),
new StaleWhileRevalidate({
cacheName: 'images',
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({maxEntries: 250}),
],
}),
);

// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
// self.addEventListener('message', (event) => {
// if (event.data && event.data.type === 'SKIP_WAITING') {
// self.skipWaiting();
// }
// });

const debugOrInspectorRegexp = /\/debug|inspect\//i;
self.addEventListener('fetch', (event) => {
const request = event.request;
if (request.mode === 'navigate') {
return;
}

if (request.url.match(fileExtensionRegexp)) {
return;
}

if (request.url.match(debugOrInspectorRegexp)) {
return;
}

event.respondWith(
fetch(event.request).then((response) => {
notify(event.clientId, request, response);

return response;
}),
);
});

function notify(clientId, request, response) {
// console.log('notify', request, response);
const events = [
{
type: 'FETCH',
payload: {
headers: Object.fromEntries(response.headers),
url: request.url,
method: request.method,
status: request.status,
},
},
];
events.map((event) => {
self.clients.get(clientId).then((client) => {
// console.log('client', client);
client.postMessage(event);
});
// self.clients.matchAll().then((all) => {
// all.map((client) => client.postMessage(eventToSend));
// });
});
}
Loading

0 comments on commit 05a2084

Please sign in to comment.