From 4971c864a603e0c01f7ad84a23697905d096283b Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Thu, 10 Nov 2022 14:35:24 +0100 Subject: feat(web): backend URL configuration To point the frontend to a backend server, update the config.json file in the website root. The config.json is generated automatically in debug mode and when running from a standalone jar. --- package.json | 2 +- subprojects/frontend/package.json | 20 +- subprojects/frontend/src/RootStore.ts | 21 +- subprojects/frontend/src/xtext/XtextClient.ts | 3 +- .../frontend/src/xtext/XtextWebSocketClient.ts | 65 +++--- .../frontend/src/xtext/fetchBackendConfig.ts | 16 ++ subprojects/frontend/src/xtext/webSocketMachine.ts | 36 +--- subprojects/frontend/types/ImportMeta.d.ts | 1 + subprojects/frontend/vite.config.ts | 25 +++ .../refinery/language/web/CacheControlFilter.java | 5 +- .../refinery/language/web/ServerLauncher.java | 29 ++- .../language/web/config/BackendConfig.java | 20 ++ .../language/web/config/BackendConfigServlet.java | 39 ++++ .../web/xtext/server/ResponseHandlerException.java | 3 + .../web/xtext/server/TransactionExecutor.java | 39 ++-- .../language/web/xtext/servlet/XtextWebSocket.java | 22 +- yarn.lock | 228 +++++++++++---------- 17 files changed, 336 insertions(+), 238 deletions(-) create mode 100644 subprojects/frontend/src/xtext/fetchBackendConfig.ts create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java diff --git a/package.json b/package.json index 2f047d76..fd5c226a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "packageManager": "yarn@3.2.4", "devDependencies": { - "eslint": "^8.26.0", + "eslint": "^8.27.0", "typescript": "4.8.4" } } diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json index 10de68ee..ed4b101b 100644 --- a/subprojects/frontend/package.json +++ b/subprojects/frontend/package.json @@ -29,21 +29,21 @@ "@codemirror/lint": "^6.0.0", "@codemirror/search": "^6.2.2", "@codemirror/state": "^6.1.2", - "@codemirror/view": "^6.4.0", + "@codemirror/view": "^6.4.1", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@fontsource/inter": "^4.5.14", "@fontsource/jetbrains-mono": "^4.5.11", "@lezer/common": "^1.0.1", "@lezer/highlight": "^1.1.2", - "@lezer/lr": "^1.2.3", + "@lezer/lr": "^1.2.4", "@material-icons/svg": "^1.0.33", "@mui/icons-material": "5.10.9", - "@mui/material": "5.10.12", + "@mui/material": "5.10.13", "ansi-styles": "^6.2.1", "escape-string-regexp": "^5.0.0", "lodash-es": "^4.17.21", - "loglevel": "^1.8.0", + "loglevel": "^1.8.1", "loglevel-plugin-prefix": "^0.8.4", "mobx": "^6.6.2", "mobx-react-lite": "^3.4.0", @@ -56,7 +56,7 @@ "zod": "^3.19.1" }, "devDependencies": { - "@lezer/generator": "^1.1.1", + "@lezer/generator": "^1.1.3", "@types/eslint": "^8.4.10", "@types/html-minifier-terser": "^7.0.0", "@types/lodash-es": "^4.17.6", @@ -65,12 +65,12 @@ "@types/prettier": "^2.7.1", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.8", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", + "@typescript-eslint/eslint-plugin": "^5.42.1", + "@typescript-eslint/parser": "^5.42.1", "@vitejs/plugin-react": "^2.2.0", "@xstate/cli": "^0.3.3", "cross-env": "^7.0.3", - "eslint": "^8.26.0", + "eslint": "^8.27.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-prettier": "^8.5.0", @@ -84,9 +84,9 @@ "html-minifier-terser": "^7.0.0", "prettier": "^2.7.1", "typescript": "4.8.4", - "vite": "^3.2.2", + "vite": "^3.2.3", "vite-plugin-inject-preload": "^1.1.0", - "vite-plugin-pwa": "^0.13.2", + "vite-plugin-pwa": "^0.13.3", "workbox-window": "^6.5.4" } } diff --git a/subprojects/frontend/src/RootStore.ts b/subprojects/frontend/src/RootStore.ts index 54a80501..2e76d66d 100644 --- a/subprojects/frontend/src/RootStore.ts +++ b/subprojects/frontend/src/RootStore.ts @@ -23,18 +23,17 @@ export default class RootStore { pwaStore: false, themeStore: false, }); - import('./editor/EditorStore') - .then(({ default: EditorStore }) => { - runInAction(() => { - if (this.disposed) { - return; - } - this.editorStore = new EditorStore(initialValue, this.pwaStore); - }); - }) - .catch((error) => { - log.error('Failed to load EditorStore', error); + (async () => { + const { default: EditorStore } = await import('./editor/EditorStore'); + runInAction(() => { + if (this.disposed) { + return; + } + this.editorStore = new EditorStore(initialValue, this.pwaStore); }); + })().catch((error) => { + log.error('Failed to load EditorStore', error); + }); } dispose(): void { diff --git a/subprojects/frontend/src/xtext/XtextClient.ts b/subprojects/frontend/src/xtext/XtextClient.ts index e7d26ae6..14fb2430 100644 --- a/subprojects/frontend/src/xtext/XtextClient.ts +++ b/subprojects/frontend/src/xtext/XtextClient.ts @@ -35,8 +35,7 @@ export default class XtextClient { this.webSocketClient = new XtextWebSocketClient( () => this.onReconnect(), () => this.onDisconnect(), - (resource, stateId, service, push) => - this.onPush(resource, stateId, service, push), + this.onPush.bind(this), ); this.updateService = new UpdateService(store, this.webSocketClient); this.contentAssistService = new ContentAssistService(this.updateService); diff --git a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts index a39620cb..6b734546 100644 --- a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts +++ b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts @@ -7,7 +7,8 @@ import CancelledError from '../utils/CancelledError'; import PendingTask from '../utils/PendingTask'; import getLogger from '../utils/getLogger'; -import webSocketMachine, { isWebSocketURLLocal } from './webSocketMachine'; +import fetchBackendConfig from './fetchBackendConfig'; +import webSocketMachine from './webSocketMachine'; import { type XtextWebPushService, XtextResponse, @@ -42,26 +43,18 @@ export default class XtextWebSocketClient { private readonly pendingRequests = new Map>(); private readonly interpreter = interpret( - webSocketMachine - .withContext({ - ...webSocketMachine.context, - webSocketURL: `${window.location.origin.replace( - /^http/, - 'ws', - )}/xtext-service`, - }) - .withConfig({ - actions: { - openWebSocket: ({ webSocketURL }) => this.openWebSocket(webSocketURL), - closeWebSocket: () => this.closeWebSocket(), - notifyReconnect: () => this.onReconnect(), - notifyDisconnect: () => this.onDisconnect(), - cancelPendingRequests: () => this.cancelPendingRequests(), - }, - services: { - pingService: () => this.sendPing(), - }, - }), + webSocketMachine.withConfig({ + actions: { + openWebSocket: () => this.openWebSocket(), + closeWebSocket: () => this.closeWebSocket(), + notifyReconnect: () => this.onReconnect(), + notifyDisconnect: () => this.onDisconnect(), + cancelPendingRequests: () => this.cancelPendingRequests(), + }, + services: { + pingService: () => this.sendPing(), + }, + }), { logger: log.log.bind(log), }, @@ -151,6 +144,7 @@ export default class XtextWebSocketClient { | 'webSocket' | 'interpreter' | 'openListener' + | 'openWebSocket' | 'errorListener' | 'closeListener' | 'messageListener' @@ -160,6 +154,7 @@ export default class XtextWebSocketClient { webSocket: observable.ref, interpreter: false, openListener: false, + openWebSocket: false, errorListener: false, closeListener: false, messageListener: false, @@ -221,9 +216,7 @@ export default class XtextWebSocketClient { get networkMissing(): boolean { return ( this.state.matches('connection.temporarilyOffline') || - (this.disconnectedByUser && - this.state.matches('network.offline') && - !isWebSocketURLLocal(this.state.context.webSocketURL)) + (this.disconnectedByUser && this.state.matches('network.offline')) ); } @@ -275,17 +268,27 @@ export default class XtextWebSocketClient { this.interpreter.send(document.hidden ? 'TAB_HIDDEN' : 'TAB_VISIBLE'); } - private openWebSocket(webSocketURL: string | undefined): void { + private openWebSocket(): void { if (this.webSocket !== undefined) { throw new Error('WebSocket already open'); } - if (webSocketURL === undefined) { - throw new Error('URL not configured'); - } - log.debug('Creating WebSocket'); + (async () => { + const { webSocketURL } = await fetchBackendConfig(); + this.openWebSocketWithURL(webSocketURL); + })().catch((error) => { + log.error('Error while initializing connection', error); + const message = error instanceof Error ? error.message : String(error); + this.interpreter.send({ + type: 'ERROR', + message, + }); + }); + } + + private openWebSocketWithURL(webSocketURL: string): void { this.webSocket = new WebSocket(webSocketURL, XTEXT_SUBPROTOCOL_V1); this.webSocket.addEventListener('open', this.openListener); this.webSocket.addEventListener('close', this.closeListener); @@ -295,7 +298,9 @@ export default class XtextWebSocketClient { private closeWebSocket() { if (this.webSocket === undefined) { - throw new Error('WebSocket already closed'); + // We might get here when there is a network error before the socket is initialized + // and we don't have to do anything to close it. + return; } log.debug('Closing WebSocket'); diff --git a/subprojects/frontend/src/xtext/fetchBackendConfig.ts b/subprojects/frontend/src/xtext/fetchBackendConfig.ts new file mode 100644 index 00000000..f8087a70 --- /dev/null +++ b/subprojects/frontend/src/xtext/fetchBackendConfig.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ + +import { z } from 'zod'; + +export const BackendConfig = z.object({ + webSocketURL: z.string().url(), +}); + +export type BackendConfig = z.infer; + +export default async function fetchBackendConfig(): Promise { + const configURL = `${import.meta.env.BASE_URL}config.json`; + const response = await fetch(configURL); + const rawConfig = (await response.json()) as unknown; + return BackendConfig.parse(rawConfig); +} diff --git a/subprojects/frontend/src/xtext/webSocketMachine.ts b/subprojects/frontend/src/xtext/webSocketMachine.ts index b5b40d11..5f6bc604 100644 --- a/subprojects/frontend/src/xtext/webSocketMachine.ts +++ b/subprojects/frontend/src/xtext/webSocketMachine.ts @@ -6,12 +6,10 @@ const { raise } = actions; const ERROR_WAIT_TIMES = ['200', '1s', '5s', '30s'].map(ms); export interface WebSocketContext { - webSocketURL: string | undefined; errors: string[]; } export type WebSocketEvent = - | { type: 'CONFIGURE'; webSocketURL: string } | { type: 'CONNECT' } | { type: 'DISCONNECT' } | { type: 'OPENED' } @@ -25,24 +23,6 @@ export type WebSocketEvent = | { type: 'OFFLINE' } | { type: 'ERROR'; message: string }; -export function isWebSocketURLLocal(webSocketURL: string | undefined): boolean { - if (webSocketURL === undefined) { - return false; - } - let hostname: string; - try { - ({ hostname } = new URL(webSocketURL)); - } catch { - return false; - } - // https://stackoverflow.com/a/57949518 - return ( - hostname === 'localhost' || - hostname === '[::1]' || - hostname.match(/^127(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/) !== null - ); -} - export default createMachine( { id: 'webSocket', @@ -53,7 +33,6 @@ export default createMachine( }, tsTypes: {} as import('./webSocketMachine.typegen').Typegen0, context: { - webSocketURL: undefined, errors: [], }, type: 'parallel', @@ -65,16 +44,12 @@ export default createMachine( disconnected: { id: 'disconnected', entry: ['clearErrors', 'notifyDisconnect'], - on: { - CONFIGURE: { actions: 'configure' }, - }, }, timedOut: { id: 'timedOut', always: [ { target: 'temporarilyOffline', - cond: 'needsNetwork', in: '#offline', }, { target: 'socketCreated', in: '#tabVisible' }, @@ -89,7 +64,6 @@ export default createMachine( always: [ { target: 'temporarilyOffline', - cond: 'needsNetwork', in: '#offline', }, ], @@ -183,7 +157,7 @@ export default createMachine( }, }, on: { - CONNECT: { target: '.timedOut', cond: 'hasWebSocketURL' }, + CONNECT: '.timedOut', DISCONNECT: '.disconnected', }, }, @@ -224,10 +198,6 @@ export default createMachine( }, }, { - guards: { - hasWebSocketURL: ({ webSocketURL }) => webSocketURL !== undefined, - needsNetwork: ({ webSocketURL }) => !isWebSocketURLLocal(webSocketURL), - }, delays: { IDLE_TIMEOUT: ms('5m'), OPEN_TIMEOUT: ms('10s'), @@ -239,10 +209,6 @@ export default createMachine( }, }, actions: { - configure: assign((context, { webSocketURL }) => ({ - ...context, - webSocketURL, - })), pushError: assign((context, { message }) => ({ ...context, errors: [...context.errors, message], diff --git a/subprojects/frontend/types/ImportMeta.d.ts b/subprojects/frontend/types/ImportMeta.d.ts index 2008e268..c32b48f5 100644 --- a/subprojects/frontend/types/ImportMeta.d.ts +++ b/subprojects/frontend/types/ImportMeta.d.ts @@ -1,5 +1,6 @@ interface ImportMeta { env: { + BASE_URL: string; DEV: boolean; MODE: string; PROD: boolean; diff --git a/subprojects/frontend/vite.config.ts b/subprojects/frontend/vite.config.ts index e690d005..526ea541 100644 --- a/subprojects/frontend/vite.config.ts +++ b/subprojects/frontend/vite.config.ts @@ -30,6 +30,7 @@ const apiPort = portNumberOrElse('API_PORT', 1312); const apiSecure = apiPort === 443; const publicHost = process.env.PUBLIC_HOST || listenHost; const publicPort = portNumberOrElse('PUBLIC_PORT', listenPort); +const publicSecure = publicPort === 443; const { name: packageName, version: packageVersion } = JSON.parse( readFileSync(path.join(thisDir, 'package.json'), 'utf8'), @@ -56,6 +57,23 @@ const minifyPlugin: PluginOption = { }, }; +const backendConfigPlugin: PluginOption = { + name: 'backend-config', + configureServer(server) { + const protocol = publicSecure ? 'wss' : 'ws'; + const webSocketURL = `${protocol}://${publicHost}:${publicPort}/xtext-service`; + const config = JSON.stringify({ webSocketURL }); + server.middlewares.use((req, res, next) => { + if (req.url === '/config.json') { + res.setHeader('Content-Type', 'application/json'); + res.end(config); + } else { + next(); + } + }); + }, +}; + export default defineConfig({ logLevel: 'info', mode, @@ -63,6 +81,7 @@ export default defineConfig({ cacheDir: path.join(thisDir, 'build/vite/cache'), plugins: [ minifyPlugin, + backendConfigPlugin, react(), injectPreload({ files: [ @@ -90,6 +109,12 @@ export default defineConfig({ ], dontCacheBustURLsMatching: /\.(?:css|js|woff2?)$/, navigateFallbackDenylist: [/^\/xtext-service/], + runtimeCaching: [ + { + urlPattern: 'config.json', + handler: 'StaleWhileRevalidate', + }, + ], }, includeAssets: ['apple-touch-icon.png', 'favicon.svg', 'mask-icon.svg'], manifest: { diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java index fbce62c1..fd2af1b2 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java @@ -13,8 +13,9 @@ import java.util.regex.Pattern; public class CacheControlFilter implements Filter { private static final Pattern CACHE_URI_PATTERN = Pattern.compile(".*\\.(css|gif|js|map|png|svg|woff2?)"); - private static final Set CACHE_URI_DENYLIST = Set.of("apple-touch-icon.png", "favicon.png", "favicon.svg", - "favicon-96x96.png", "icon-any.svg", "icon-192x192.png", "icon-512x512.png", "mask-icon.svg", "sw.js"); + private static final Set CACHE_URI_DENYLIST = Set.of("apple-touch-icon.png", "config.json", "favicon.png", + "favicon.svg", "favicon-96x96.png", "icon-any.svg", "icon-192x192.png", "icon-512x512.png", "mask-icon.svg", + "sw.js"); private static final Duration EXPIRY = Duration.ofDays(365); diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java index ffa61321..58c8ea4e 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java @@ -14,6 +14,7 @@ import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import tools.refinery.language.web.config.BackendConfigServlet; import tools.refinery.language.web.xtext.servlet.XtextWebSocketServlet; import java.io.File; @@ -41,11 +42,13 @@ public class ServerLauncher { private final Server server; - public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource, String[] allowedOrigins) { + public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource, String[] allowedOrigins, + String webSocketUrl) { server = new Server(bindAddress); var handler = new ServletContextHandler(); addSessionHandler(handler); addProblemServlet(handler, allowedOrigins); + addBackendConfigServlet(handler, webSocketUrl); if (baseResource != null) { handler.setBaseResource(baseResource); handler.setWelcomeFiles(new String[]{"index.html"}); @@ -76,6 +79,12 @@ public class ServerLauncher { JettyWebSocketServletContainerInitializer.configure(handler, null); } + private void addBackendConfigServlet(ServletContextHandler handler, String webSocketUrl) { + var backendConfigServletHolder = new ServletHolder(BackendConfigServlet.class); + backendConfigServletHolder.setInitParameter(BackendConfigServlet.WEBSOCKET_URL_INIT_PARAM, webSocketUrl); + handler.addServlet(backendConfigServletHolder, "/config.json"); + } + private void addDefaultServlet(ServletContextHandler handler) { var defaultServletHolder = new ServletHolder(DefaultServlet.class); var isWindows = System.getProperty("os.name").toLowerCase().contains("win"); @@ -97,7 +106,8 @@ public class ServerLauncher { var bindAddress = getBindAddress(); var baseResource = getBaseResource(); var allowedOrigins = getAllowedOrigins(); - var serverLauncher = new ServerLauncher(bindAddress, baseResource, allowedOrigins); + var webSocketUrl = getWebSocketUrl(); + var serverLauncher = new ServerLauncher(bindAddress, baseResource, allowedOrigins, webSocketUrl); serverLauncher.start(); } catch (Exception exception) { LOG.error("Fatal server error", exception); @@ -190,4 +200,19 @@ public class ServerLauncher { } return new String[]{urlWithPort}; } + + private static String getWebSocketUrl() { + String host; + int port; + var publicHost = getPublicHost(); + if (publicHost == null) { + host = getListenAddress(); + port = getListenPort(); + } else { + host = publicHost; + port = getPublicPort(); + } + var scheme = port == HTTPS_DEFAULT_PORT ? "wss" : "ws"; + return String.format("%s://%s:%d/xtext-service", scheme, host, port); + } } diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java new file mode 100644 index 00000000..2e864998 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java @@ -0,0 +1,20 @@ +package tools.refinery.language.web.config; + +import com.google.gson.annotations.SerializedName; + +public class BackendConfig { + @SerializedName("webSocketURL") + private String webSocketUrl; + + public BackendConfig(String webSocketUrl) { + this.webSocketUrl = webSocketUrl; + } + + public String getWebSocketUrl() { + return webSocketUrl; + } + + public void setWebSocketUrl(String webSocketUrl) { + this.webSocketUrl = webSocketUrl; + } +} diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java new file mode 100644 index 00000000..f314a9fa --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java @@ -0,0 +1,39 @@ +package tools.refinery.language.web.config; + +import com.google.gson.Gson; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpStatus; + +import java.io.IOException; + +public class BackendConfigServlet extends HttpServlet { + public static final String WEBSOCKET_URL_INIT_PARAM = "tools.refinery.language.web.config.BackendConfigServlet" + + ".webSocketUrl"; + + private String serializedConfig; + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + var webSocketUrl = config.getInitParameter(WEBSOCKET_URL_INIT_PARAM); + if (webSocketUrl == null) { + throw new IllegalArgumentException("Init parameter " + WEBSOCKET_URL_INIT_PARAM + " is mandatory"); + } + var backendConfig = new BackendConfig(webSocketUrl); + var gson = new Gson(); + serializedConfig = gson.toJson(backendConfig); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setStatus(HttpStatus.OK_200); + resp.setContentType("application/json"); + var writer = resp.getWriter(); + writer.write(serializedConfig); + writer.flush(); + } +} diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java index 34fcb546..b686d33a 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java @@ -1,7 +1,10 @@ package tools.refinery.language.web.xtext.server; +import java.io.Serial; + public class ResponseHandlerException extends Exception { + @Serial private static final long serialVersionUID = 3589866922420268164L; public ResponseHandlerException(String message, Throwable cause) { diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java index 0b417b06..7bb11d2e 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java @@ -1,35 +1,25 @@ package tools.refinery.language.web.xtext.server; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.google.common.base.Strings; +import com.google.inject.Injector; import org.eclipse.emf.common.util.URI; import org.eclipse.xtext.resource.IResourceServiceProvider; import org.eclipse.xtext.util.IDisposable; -import org.eclipse.xtext.web.server.IServiceContext; -import org.eclipse.xtext.web.server.IServiceResult; -import org.eclipse.xtext.web.server.ISession; -import org.eclipse.xtext.web.server.InvalidRequestException; +import org.eclipse.xtext.web.server.*; import org.eclipse.xtext.web.server.InvalidRequestException.UnknownLanguageException; -import org.eclipse.xtext.web.server.XtextServiceDispatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.google.common.base.Strings; -import com.google.inject.Injector; - -import tools.refinery.language.web.xtext.server.message.XtextWebErrorKind; -import tools.refinery.language.web.xtext.server.message.XtextWebErrorResponse; -import tools.refinery.language.web.xtext.server.message.XtextWebOkResponse; -import tools.refinery.language.web.xtext.server.message.XtextWebPushMessage; -import tools.refinery.language.web.xtext.server.message.XtextWebRequest; +import tools.refinery.language.web.xtext.server.message.*; import tools.refinery.language.web.xtext.server.push.PrecomputationListener; import tools.refinery.language.web.xtext.server.push.PushWebDocument; import tools.refinery.language.web.xtext.servlet.SimpleServiceContext; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class TransactionExecutor implements IDisposable, PrecomputationListener { private static final Logger LOG = LoggerFactory.getLogger(TransactionExecutor.class); @@ -41,11 +31,11 @@ public class TransactionExecutor implements IDisposable, PrecomputationListener private ResponseHandler responseHandler; - private Object callPendingLock = new Object(); + private final Object callPendingLock = new Object(); private boolean callPending; - private List pendingPushMessages = new ArrayList<>(); + private final List pendingPushMessages = new ArrayList<>(); public TransactionExecutor(ISession session, IResourceServiceProvider.Registry resourceServiceProviderRegistry) { this.session = session; @@ -132,10 +122,9 @@ public class TransactionExecutor implements IDisposable, PrecomputationListener /** * Get the injector to satisfy the request in the {@code serviceContext}. - * * Based on {@link org.eclipse.xtext.web.servlet.XtextServlet#getInjector}. - * - * @param serviceContext the Xtext service context of the request + * + * @param context the Xtext service context of the request * @return the injector for the Xtext language in the request * @throws UnknownLanguageException if the Xtext language cannot be determined */ diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java index fd41f213..82391d8b 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java @@ -1,31 +1,25 @@ package tools.refinery.language.web.xtext.servlet; -import java.io.IOException; -import java.io.Reader; - +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonParseException; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WriteCallback; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; -import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.api.annotations.*; import org.eclipse.xtext.resource.IResourceServiceProvider; import org.eclipse.xtext.web.server.ISession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.google.gson.Gson; -import com.google.gson.JsonIOException; -import com.google.gson.JsonParseException; - import tools.refinery.language.web.xtext.server.ResponseHandler; import tools.refinery.language.web.xtext.server.ResponseHandlerException; import tools.refinery.language.web.xtext.server.TransactionExecutor; import tools.refinery.language.web.xtext.server.message.XtextWebRequest; import tools.refinery.language.web.xtext.server.message.XtextWebResponse; +import java.io.IOException; +import java.io.Reader; + @WebSocket public class XtextWebSocket implements WriteCallback, ResponseHandler { private static final Logger LOG = LoggerFactory.getLogger(XtextWebSocket.class); @@ -118,7 +112,7 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { webSocketSession.getRemote().sendPartialString(responseString, true, this); } catch (IOException e) { throw new ResponseHandlerException( - "Cannot initiaite async write to websocket " + webSocketSession.getRemoteAddress(), e); + "Cannot initiate async write to websocket " + webSocketSession.getRemoteAddress(), e); } } diff --git a/yarn.lock b/yarn.lock index 3834353e..2d4e7d31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1407,14 +1407,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.4.0": - version: 6.4.0 - resolution: "@codemirror/view@npm:6.4.0" +"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.4.1": + version: 6.4.1 + resolution: "@codemirror/view@npm:6.4.1" dependencies: "@codemirror/state": ^6.0.0 style-mod: ^4.0.0 w3c-keyname: ^2.2.4 - checksum: 57ed7d9d51907f1ea549a2a158872fb7affa6cdff72e29e214f8437b7142ea2a2431ac3c780cbc0187dfff7cb5fd1055a45a887ea9b8c2a09d8430c60ebe9083 + checksum: 51f8e9bf1701cd490708784fd42a90dd9b2ad84aaebfacdbcfa9093e7f99ded38093ac49bc9eb037924b7734a58ed854a19621d931cce3f7962c2a0b30fecc23 languageName: node linkType: hard @@ -1719,15 +1719,15 @@ __metadata: languageName: node linkType: hard -"@lezer/generator@npm:^1.1.1": - version: 1.1.1 - resolution: "@lezer/generator@npm:1.1.1" +"@lezer/generator@npm:^1.1.3": + version: 1.1.3 + resolution: "@lezer/generator@npm:1.1.3" dependencies: "@lezer/common": ^1.0.0 "@lezer/lr": ^1.0.0 bin: lezer-generator: dist/lezer-generator.cjs - checksum: 16638471b593a40db5052f22df387bba323dba49dc92712927e86bc1333786680bbbaef24c16c81659e226da05d4583728641567d4058997de39e9aa6d4cdf20 + checksum: 50057aa2bdad39f2c30296e0043e5565a6020efc1ffd0729d25e0e07ef6037a8f151fcebdbcb9fa91bab676e9ecbd2edb4dba9e486a5c8f1a67d0bc1b7c92622 languageName: node linkType: hard @@ -1740,12 +1740,12 @@ __metadata: languageName: node linkType: hard -"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.2.3": - version: 1.2.3 - resolution: "@lezer/lr@npm:1.2.3" +"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.2.4": + version: 1.2.4 + resolution: "@lezer/lr@npm:1.2.4" dependencies: "@lezer/common": ^1.0.0 - checksum: 118db077d32f6eb9d6b219c766d7e5715c6c004d89d76ed0137ea2a364aeca67f21dc5924ea67a649b5de1d13bfbb85571923b38536e6995820eb0a5c8844594 + checksum: c3351c7e51692591abf84bdcf881a6c7547861b26f3f783ec75ead37d976dc21ec43ccdac315cb6cdfd9295b58db55bb42da3dd53ea05836a9f7f9e49c2d4c91 languageName: node linkType: hard @@ -1756,9 +1756,9 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-alpha.104": - version: 5.0.0-alpha.104 - resolution: "@mui/base@npm:5.0.0-alpha.104" +"@mui/base@npm:5.0.0-alpha.105": + version: 5.0.0-alpha.105 + resolution: "@mui/base@npm:5.0.0-alpha.105" dependencies: "@babel/runtime": ^7.19.0 "@emotion/is-prop-valid": ^1.2.0 @@ -1775,14 +1775,14 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: f66693b4659bb50cc89b6b0e055db45d091bb546f82a4c6cc230f3699e647b68c941dcb8e8d42648e3470f83da5600f400ff21af9a8f7aaf6b018ac5ad3ceeb1 + checksum: 1db3dcd6760c814437c679ddf13d9e3c4e7fc6f51ce933445715a56aa65dcaeb38aff35832c524211d62fb3401b436cbcc3e9e4234068a0c3379da727f44cff2 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.10.12": - version: 5.10.12 - resolution: "@mui/core-downloads-tracker@npm:5.10.12" - checksum: 894c7ee810851de2ee5de43648822e6f5ea639e4ab494fd54c9a6cb6dbace608b5634699fab05978f2d21efc4378bbce83b8352ef7aa958afd3d387c32373244 +"@mui/core-downloads-tracker@npm:^5.10.13": + version: 5.10.13 + resolution: "@mui/core-downloads-tracker@npm:5.10.13" + checksum: 175d5779e8e4b6130c96d2ce990047ea58571f847a7041ca273564edc5411456296d1e094e350970d1294c4cc4d8459ea237f69e7917926a6530d5195fb41cc6 languageName: node linkType: hard @@ -1802,14 +1802,14 @@ __metadata: languageName: node linkType: hard -"@mui/material@npm:5.10.12": - version: 5.10.12 - resolution: "@mui/material@npm:5.10.12" +"@mui/material@npm:5.10.13": + version: 5.10.13 + resolution: "@mui/material@npm:5.10.13" dependencies: "@babel/runtime": ^7.19.0 - "@mui/base": 5.0.0-alpha.104 - "@mui/core-downloads-tracker": ^5.10.12 - "@mui/system": ^5.10.12 + "@mui/base": 5.0.0-alpha.105 + "@mui/core-downloads-tracker": ^5.10.13 + "@mui/system": ^5.10.13 "@mui/types": ^7.2.0 "@mui/utils": ^5.10.9 "@types/react-transition-group": ^4.4.5 @@ -1831,7 +1831,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 37b3d605d0cdb5136ac5a568d1c3c00ad5a3e01242cea6bccad5ccb08512e3c600dde75af852515c947b994fb5afa972044faac07416d347cbb6e503651c23a3 + checksum: 817e61e575a47b60cba54f826e8a090399f9332b192e2632efa9f82ae6bc44653fe6ab3606c047c29686a5b4ee3ec7bbd69b89c9a0dd6ca1e382aff23c0e5c96 languageName: node linkType: hard @@ -1873,9 +1873,9 @@ __metadata: languageName: node linkType: hard -"@mui/system@npm:^5.10.12": - version: 5.10.12 - resolution: "@mui/system@npm:5.10.12" +"@mui/system@npm:^5.10.13": + version: 5.10.13 + resolution: "@mui/system@npm:5.10.13" dependencies: "@babel/runtime": ^7.19.0 "@mui/private-theming": ^5.10.9 @@ -1897,7 +1897,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 1803a6f54bc1fda304834f362c60697b2ee157df7629b26337cb3d180093cbc244a94df45719da436b2917f98674687a98fea353a9ec8e6de7c5c3b5ba592bc8 + checksum: afac3f4859b9e137fa62fa4446642909704964209a44f63a472d452ace6428a0b337b48a934cd805e3728a0098ad4f41fedbc06ce14e245a5fa42fabe349d9e8 languageName: node linkType: hard @@ -2006,18 +2006,18 @@ __metadata: "@codemirror/lint": ^6.0.0 "@codemirror/search": ^6.2.2 "@codemirror/state": ^6.1.2 - "@codemirror/view": ^6.4.0 + "@codemirror/view": ^6.4.1 "@emotion/react": ^11.10.5 "@emotion/styled": ^11.10.5 "@fontsource/inter": ^4.5.14 "@fontsource/jetbrains-mono": ^4.5.11 "@lezer/common": ^1.0.1 - "@lezer/generator": ^1.1.1 + "@lezer/generator": ^1.1.3 "@lezer/highlight": ^1.1.2 - "@lezer/lr": ^1.2.3 + "@lezer/lr": ^1.2.4 "@material-icons/svg": ^1.0.33 "@mui/icons-material": 5.10.9 - "@mui/material": 5.10.12 + "@mui/material": 5.10.13 "@types/eslint": ^8.4.10 "@types/html-minifier-terser": ^7.0.0 "@types/lodash-es": ^4.17.6 @@ -2026,14 +2026,14 @@ __metadata: "@types/prettier": ^2.7.1 "@types/react": ^18.0.25 "@types/react-dom": ^18.0.8 - "@typescript-eslint/eslint-plugin": ^5.42.0 - "@typescript-eslint/parser": ^5.42.0 + "@typescript-eslint/eslint-plugin": ^5.42.1 + "@typescript-eslint/parser": ^5.42.1 "@vitejs/plugin-react": ^2.2.0 "@xstate/cli": ^0.3.3 ansi-styles: ^6.2.1 cross-env: ^7.0.3 escape-string-regexp: ^5.0.0 - eslint: ^8.26.0 + eslint: ^8.27.0 eslint-config-airbnb: ^19.0.4 eslint-config-airbnb-typescript: ^17.0.0 eslint-config-prettier: ^8.5.0 @@ -2046,7 +2046,7 @@ __metadata: eslint-plugin-react-hooks: ^4.6.0 html-minifier-terser: ^7.0.0 lodash-es: ^4.17.21 - loglevel: ^1.8.0 + loglevel: ^1.8.1 loglevel-plugin-prefix: ^0.8.4 mobx: ^6.6.2 mobx-react-lite: ^3.4.0 @@ -2057,9 +2057,9 @@ __metadata: react: ^18.2.0 react-dom: ^18.2.0 typescript: 4.8.4 - vite: ^3.2.2 + vite: ^3.2.3 vite-plugin-inject-preload: ^1.1.0 - vite-plugin-pwa: ^0.13.2 + vite-plugin-pwa: ^0.13.3 workbox-window: ^6.5.4 xstate: ^4.34.0 zod: ^3.19.1 @@ -2070,7 +2070,7 @@ __metadata: version: 0.0.0-use.local resolution: "@refinery/root@workspace:." dependencies: - eslint: ^8.26.0 + eslint: ^8.27.0 typescript: 4.8.4 languageName: unknown linkType: soft @@ -2120,6 +2120,18 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-replace@npm:^4.0.0": + version: 4.0.0 + resolution: "@rollup/plugin-replace@npm:4.0.0" + dependencies: + "@rollup/pluginutils": ^3.1.0 + magic-string: ^0.25.7 + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + checksum: b61701e612661a46da06ca88f390c3839b586708abc0329a476411b90aa8ac59fe94437ede4c3fe53fea268b3054ea9d7d4ee851d7bd0cb7a5f06906002067cb + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^3.1.0": version: 3.1.0 resolution: "@rollup/pluginutils@npm:3.1.0" @@ -2316,13 +2328,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/eslint-plugin@npm:5.42.0" +"@typescript-eslint/eslint-plugin@npm:^5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/eslint-plugin@npm:5.42.1" dependencies: - "@typescript-eslint/scope-manager": 5.42.0 - "@typescript-eslint/type-utils": 5.42.0 - "@typescript-eslint/utils": 5.42.0 + "@typescript-eslint/scope-manager": 5.42.1 + "@typescript-eslint/type-utils": 5.42.1 + "@typescript-eslint/utils": 5.42.1 debug: ^4.3.4 ignore: ^5.2.0 natural-compare-lite: ^1.4.0 @@ -2335,43 +2347,43 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 8dd13c77f5b83a8ba7e37196769b9c8a296c4417ffe7e33cb4d172495e1596ea0a9140dae0f1bbe1317a0cd5d5d92bf76a1799e7b9f8b3a577433b9569f1436d + checksum: 6e80b15df7e655964ddd3041d5f7c0bf564e9901f9e3a9cdaf8d056301841fad8d40cd253d83669f01e0ddc62521af9286a27f098df43e304cf932d768995e98 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/parser@npm:5.42.0" +"@typescript-eslint/parser@npm:^5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/parser@npm:5.42.1" dependencies: - "@typescript-eslint/scope-manager": 5.42.0 - "@typescript-eslint/types": 5.42.0 - "@typescript-eslint/typescript-estree": 5.42.0 + "@typescript-eslint/scope-manager": 5.42.1 + "@typescript-eslint/types": 5.42.1 + "@typescript-eslint/typescript-estree": 5.42.1 debug: ^4.3.4 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 790d5fcc53f02a25628b1d2a06e3b7f26f4fa12e78f51a67e1db0ac6a4b643a34f247991d7b938f45c7f8395fcaf920807c8a29d768913a7a8266162d2244806 + checksum: 7208a085102be5c569ac2be5799d05e080a9c0b9157ed3efa5d7eadb675185bddfa05f2f27e20c235910193a2bd835e5375fb9fc13561a6e20d110e444f37caa languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/scope-manager@npm:5.42.0" +"@typescript-eslint/scope-manager@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/scope-manager@npm:5.42.1" dependencies: - "@typescript-eslint/types": 5.42.0 - "@typescript-eslint/visitor-keys": 5.42.0 - checksum: c7dac787c27db640ef8add18e91f84ade36871a50e84f36604fc1b823fc544ad28cea4731c4b7cadec157964f5399e6db2b3a9a115b2a2dd97fbc2bae7b1f9e0 + "@typescript-eslint/types": 5.42.1 + "@typescript-eslint/visitor-keys": 5.42.1 + checksum: cfad5f04328fae4bb6d965a94c980ac2f6fa0eee6183e9bed6d7ebdb067f01a0a9a3b5500fc3638d5e287f46f4412aa462e238c610c1fb96b794b83c575c7fb4 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/type-utils@npm:5.42.0" +"@typescript-eslint/type-utils@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/type-utils@npm:5.42.1" dependencies: - "@typescript-eslint/typescript-estree": 5.42.0 - "@typescript-eslint/utils": 5.42.0 + "@typescript-eslint/typescript-estree": 5.42.1 + "@typescript-eslint/utils": 5.42.1 debug: ^4.3.4 tsutils: ^3.21.0 peerDependencies: @@ -2379,23 +2391,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5c98bdff38d8ace74f77b792d97572c41e3d0d01506529a32bc1244791a9e933d06dcc516eaad5bf1fc85b2cf1a95642f519f9c4ce4d6a974481e1a3680ed8dd + checksum: 7ac3180aeb966351e54055440f42b723aa864fd39c74be5a41aae97401e6424df94d9f96ae945f1c3a6023860ffd7ba424ff6506c21bd373a6cd878466d9ba62 languageName: node linkType: hard -"@typescript-eslint/types@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/types@npm:5.42.0" - checksum: 7a17ff007972129a1e2105a653d8aa637070b74d4f8b98309aeb83d06076ab40cebfa1c3e9aae3fc614118e730c4539ff13e8299d34530851cb06260483ef14c +"@typescript-eslint/types@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/types@npm:5.42.1" + checksum: b0eb3df3792dd0e447abcf2b4fd79b2eaa6f944242d00afa8ef2d9f892ea63e52f200e7cb1758ddbc46154aa6764cec8bc796ed96f7554457a20db976f9f2089 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.42.0" +"@typescript-eslint/typescript-estree@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/typescript-estree@npm:5.42.1" dependencies: - "@typescript-eslint/types": 5.42.0 - "@typescript-eslint/visitor-keys": 5.42.0 + "@typescript-eslint/types": 5.42.1 + "@typescript-eslint/visitor-keys": 5.42.1 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -2404,35 +2416,35 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: cc8a98815daf6c8bf6f8f5e43c4a7bf7008aa850cecc669de7b8cfdddb0648fd2eae738a185165176a24aed360cb12204cc0808f251e9fcf8e436cd15fff3645 + checksum: dfd3e20d41ba4b574a52d82cc40b38708b8c2c4277d6304a8d914fe2a4a9ce8779f4d79fdac140e77a3afd3c6a2a7e3f31620dc427cabd04e4e906bb0ca3a468 languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/utils@npm:5.42.0" +"@typescript-eslint/utils@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/utils@npm:5.42.1" dependencies: "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.42.0 - "@typescript-eslint/types": 5.42.0 - "@typescript-eslint/typescript-estree": 5.42.0 + "@typescript-eslint/scope-manager": 5.42.1 + "@typescript-eslint/types": 5.42.1 + "@typescript-eslint/typescript-estree": 5.42.1 eslint-scope: ^5.1.1 eslint-utils: ^3.0.0 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: cc57ba8bdf1cf18de5c6c264b71be80dc8c4a7630c0d6a34f73ed991cd3684c97a06605f414a8fd439ce2201f7724249b2fc29eac1e54a770ee4e8303cabef52 + checksum: 9f1c429a602dad4ba7a52df00924aab6033854234a1e1bf699a3e5b48455b5fdc1a41de459a7f11a3ccfed1528831ecb95fc7e54d30be7d8cccbb689f885fdac languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.42.0": - version: 5.42.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.42.0" +"@typescript-eslint/visitor-keys@npm:5.42.1": + version: 5.42.1 + resolution: "@typescript-eslint/visitor-keys@npm:5.42.1" dependencies: - "@typescript-eslint/types": 5.42.0 + "@typescript-eslint/types": 5.42.1 eslint-visitor-keys: ^3.3.0 - checksum: d198e51ea968555dd44b3ff14587dd82ce43c30ae43d4021d4eacb468e4476102a5b715e15240adcdeec4b4b5280d819087a9c4090360f1e4dcb05829ea8f2dc + checksum: d36c59da7bf3b3c150c12cbe4b0331edc15253f59599ec3d8b873b2a3d9fc7a4fea11490c1b20d972afcdc9c842deb5ada527ea9c538aa7e87555699d9a59f24 languageName: node linkType: hard @@ -3902,9 +3914,9 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.26.0": - version: 8.26.0 - resolution: "eslint@npm:8.26.0" +"eslint@npm:^8.27.0": + version: 8.27.0 + resolution: "eslint@npm:8.27.0" dependencies: "@eslint/eslintrc": ^1.3.3 "@humanwhocodes/config-array": ^0.11.6 @@ -3947,7 +3959,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: a2aced939ea060f77d10dcfced5cfeb940f63f383fd7ab1decadea64170ab552582e1c5909db1db641d4283178c9bc569f19b0f8900e00314a5f783e4b3f759d + checksum: 153b022d309e1b647a73b1bb0fa98912add699b06e279084155f23c6f2b5fc5abd05411fc1ba81608a24bbfaf044ca079544c16fffa6fc987b8f676c9960a2c4 languageName: node linkType: hard @@ -5050,10 +5062,10 @@ __metadata: languageName: node linkType: hard -"loglevel@npm:^1.8.0": - version: 1.8.0 - resolution: "loglevel@npm:1.8.0" - checksum: 41aeea17de24aba8dba68084a31fe9189648bce4f39c1277e021bb276c3c53a75b0d337395919cf271068ad40ecefabad0e4fdeb4a8f11908beee532b898f4a7 +"loglevel@npm:^1.8.1": + version: 1.8.1 + resolution: "loglevel@npm:1.8.1" + checksum: a1a62db40291aaeaef2f612334c49e531bff71cc1d01a2acab689ab80d59e092f852ab164a5aedc1a752fdc46b7b162cb097d8a9eb2cf0b299511106c29af61d languageName: node linkType: hard @@ -6746,10 +6758,11 @@ __metadata: languageName: node linkType: hard -"vite-plugin-pwa@npm:^0.13.2": - version: 0.13.2 - resolution: "vite-plugin-pwa@npm:0.13.2" +"vite-plugin-pwa@npm:^0.13.3": + version: 0.13.3 + resolution: "vite-plugin-pwa@npm:0.13.3" dependencies: + "@rollup/plugin-replace": ^4.0.0 debug: ^4.3.4 fast-glob: ^3.2.11 pretty-bytes: ^6.0.0 @@ -6760,13 +6773,13 @@ __metadata: vite: ^3.1.0 workbox-build: ^6.5.4 workbox-window: ^6.5.4 - checksum: 6a8383dd0782e29c6c0bce0d3838ce5213c37c898fea874802df4f3f70f9cc021a0387f9f18f812da7f3598bf885c471618570ea4da2ca32a6874e8a7213ea16 + checksum: be1e8699e2fb4fea98454d20c8df4bcbd828aecb2b714a1251405fde4dc9ac9c95520b33fdfc1a3d91d51f9d920501d93f57f4f0a2f1361ba38785c86e4756a4 languageName: node linkType: hard -"vite@npm:^3.2.2": - version: 3.2.2 - resolution: "vite@npm:3.2.2" +"vite@npm:^3.2.3": + version: 3.2.3 + resolution: "vite@npm:3.2.3" dependencies: esbuild: ^0.15.9 fsevents: ~2.3.2 @@ -6774,6 +6787,7 @@ __metadata: resolve: ^1.22.1 rollup: ^2.79.1 peerDependencies: + "@types/node": ">= 14" less: "*" sass: "*" stylus: "*" @@ -6783,6 +6797,8 @@ __metadata: fsevents: optional: true peerDependenciesMeta: + "@types/node": + optional: true less: optional: true sass: @@ -6795,7 +6811,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 7197ac91c612dda922367a95afa1b210353d6168d41845c186e2217bda1328d17b021b93d8089e336f9533b94645ae5dca18bb10937759f559c87006dd957fcd + checksum: 3c7c618f7fb471cdfaf7f8eb769cb5f4174447e1103cd6221cbc2ae1ea1102bc28dd6a621ead250e6aa42c1e9ee3c8092666ea81078e1d88d2325c484218fd0a languageName: node linkType: hard -- cgit v1.2.3-70-g09d2