npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mxs-query-editor

v1.0.8

Published

MaxScale query editor UI

Downloads

198

Readme

MaxScale Query Editor UI

This package only supports webpack 4 and Vue.js 2.

Installation

npm i mxs-query-editor

Query editor peerDependencies

| Dependency | Version | | ---------------------------- | :-----: | | @mdi/font | 7.0.x | | axios | 0.27.x | | browser-fs-access | 0.30.x | | chart.js | 2.9.x | | chartjs-plugin-trendline | 0.2.x | | deep-diff | 1.0.x | | immutability-helper | 3.1.x | | localforage | 1.10.x | | lodash | 4.17.x | | monaco-editor | 0.33.x | | monaco-editor-webpack-plugin | 7.0.x | | sql-formatter | 4.0.x | | stacktrace-parser | 0.1.x | | typy | 3.3.x | | uuid | 8.3.x | | vue | 2.x | | vue-chartjs | 3.5.x | | vue-i18n | 8.x | | vue-moment | 4.x | | vue-shortkey | 3.x | | vue-template-compiler | 2.x | | vuetify | 2.6.x | | vuex | 3.6.x | | vuex-persist | 3.1.x |

Example of registering the plugin

Registering MaxScale Query Editor plugin

// main.js
import Vue from 'vue'
import shortkey from '@/plugins/shortkey'
import typy from '@/plugins/typy'
import VueMoment from 'vue-moment'
import VueI18n from 'vue-i18n'
import Vuex from 'vuex'
import Vuetify from 'vuetify/lib'
import { Resize } from 'vuetify/lib/directives'
import MxsQueryEditor from 'mxs-query-editor'
import vuetify from '@/plugins/vuetify'
import i18n from '@/plugins/i18n'
import App from '@/App.vue'

Vue.use(shortkey)
Vue.use(typy)
Vue.use(VueMoment)
Vue.use(VueI18n)
Vue.use(Vuex)
Vue.use(Vuetify, { directives: { Resize } })
Vue.use(Vuetify)
/* store and i18n must be valid and defined.
 * e.g. Vue.use(Vuex) is called before importing store.
 */
Vue.use(MxsQueryEditor, {
    store: require('./store/index').default,
    i18n: require('@/plugins/i18n').default,
    // a list of component name to be hidden
    hidden_comp: ['wke-nav-ctr'],
})

new Vue({
    vuetify,
    i18n,
    render: h => h(App),
}).$mount('#app')

Merging locale messages. Query editor scopes its messages in the queryEditor key to prevent existing keys from being overwritten when merging locales.

// plugins/i18n.js
import VueI18n from 'vue-i18n'
const merge = require('lodash/merge')
function getMsgs(locales) {
    const messages = {}
    locales.keys().forEach(key => {
        const matched = key.match(/([A-Za-z0-9-_]+)\./i)
        if (matched && matched.length > 1) {
            const locale = matched[1]
            messages[locale] = locales(key)
        }
    })
    return messages
}
function loadLocaleMessages() {
    // Get query editor messages.
    const queryEditorMsgs = getMsgs(
        require.context('mxs-query-editor/dist/locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
    )
    const messages = getMsgs(require.context('@/locales', true, /[A-Za-z0-9-_,\s]+\.json$/i))
    return merge(messages, queryEditorMsgs)
}

export default new VueI18n({
    locale: process.env.VUE_APP_I18N_LOCALE || 'en',
    fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
    messages: loadLocaleMessages(),
})

Merging query editor custom icons. Query editor registers its custom icons via Vuetify. These icons have an mxs_ prefix to prevent existing icons from being overwritten. e.g. $vuetify.icons.mxs_edit

// plugins/vuetify.js
import Vuetify from 'vuetify/lib'
import icons from 'icons'
import queryEditorIcons from 'mxs-query-editor/dist/icons'
import i18n from './i18n'
import vuetifyTheme from './vuetifyTheme'
import '@mdi/font/css/materialdesignicons.css'

export default new Vuetify({
    icons: {
        iconfont: 'mdi',
        values: { ...icons, ...queryEditorIcons },
    },
    theme: {
        themes: {
            light: {
                primary: '#0e9bc0',
                secondary: '#E6EEF1',
                accent: '#2f99a3',
                ['accent-dark']: '#0b718c',
                success: '#7dd012',
                error: '#eb5757',
                warning: '#f59d34',
                info: '#2d9cdb',
                anchor: '#2d9cdb',
                navigation: '#424F62',
                ['deep-ocean']: '#003545',
                ['blue-azure']: '#0e6488',
            },
        },
    },
    lang: {
        t: (key, ...params) => i18n.t(key, params),
    },
})

Register query editor vuex plugins. Query editor internally uses vuex-persist and localforage packages to persist its states. So this needs to be registered manually.

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { queryEditorStorePlugins } from 'mxs-query-editor'

export default new Vuex.Store({
    namespaced: true,
    plugins: queryEditorStorePlugins,
})

Use mxs-query-editor and its sub components

The mxs-query-editor component is registered at global scope, so it can be used without importing.

If the hidden_comp option is provided when registering the plugin, the components in the list won't be rendered. e.g. hidden_comp: ['wke-nav-ctr']. For now, only wke-nav-ctr will be applied.

Certain components can be manually imported and placed somewhere else outside the mxs-query-editor component. At the moment, the following components in the below example are importable.

<!-- SkyQuery.vue -->
<template>
    <div class="query-editor-page">
        <ConfirmLeaveDlg
            v-model="isConfDlgOpened"
            :onSave="onLeave"
            :shouldDelAll.sync="shouldDelAll"
            @on-close="cancelLeave"
            @on-cancel="cancelLeave"
        />
        <ReconnDlgCtr :onReconnectCb="onReconnectCb" />
        <mxs-query-editor>
            <!-- Slot for placing content at the top of the query editor that is above the worksheet
                 navigation tabs.
            -->
            <template v-slot:query-editor-top>
                <div class="d-flex flex-wrap">
                    <v-spacer />
                    <QueryCnfGearBtn />
                    <MinMaxBtnCtr />
                </div>
            </template>
            <!-- txt-editor-toolbar-right-slot`: Slot for placing content on the right side of
                 the toolbar below the query navigation tabs in TXT_EDITOR and DDL_EDITOR modes
            -->
            <template v-slot:txt-editor-toolbar-right-slot>
                <div class="d-flex flex-wrap">
                    <v-spacer />
                    <QueryCnfGearBtn />
                    <MinMaxBtnCtr />
                </div>
            </template>
            <template v-slot:ddl-editor-toolbar-right-slot>
                <div class="d-flex flex-wrap">
                    <v-spacer />
                    <QueryCnfGearBtn />
                    <MinMaxBtnCtr />
                </div>
            </template>
        </mxs-query-editor>
    </div>
</template>

<script>
import { mapActions, mapState } from 'vuex'
import { MinMaxBtnCtr, QueryCnfGearBtn, ConfirmLeaveDlg, ReconnDlgCtr } from 'mxs-query-editor'
export default {
    name: 'query-page',
    components: {
        QueryCnfGearBtn, // Query configuration button
        MinMaxBtnCtr, // Toggle full-screen mode button
        ConfirmLeaveDlg, // confirmation on leave dialog
        ReconnDlgCtr, // reconnect dialog
    },
    data() {
        return {
            isConfDlgOpened: false,
            shouldDelAll: true,
            to: '',
        }
    },
    computed: {
        ...mapState({
            sql_conns: state => state.queryConn.sql_conns,
        }),
    },
    beforeRouteLeave(to, from, next) {
        if (this.to) {
            next()
        } else {
            this.to = to
            if (Object.keys(this.sql_conns).length === 0) this.leavePage()
            else {
                this.shouldDelAll = true
                this.isConfDlgOpened = true
            }
        }
    },
    async created() {
        await this.validateConns({ sqlConns: this.sql_conns })
    },
    methods: {
        ...mapActions({
            disconnectAll: 'queryConn/disconnectAll',
            validateConns: 'queryConn/validateConns',
        }),
        async onLeave() {
            if (this.shouldDelAll) await this.disconnectAll()
            this.leavePage()
        },
        leavePage() {
            this.$router.push(this.to)
        },
        cancelLeave() {
            this.to = null
        },
        async onReconnectCb() {
            await this.validateConns({ sqlConns: this.sql_conns, silentValidation: true })
        },
    },
}
</script>
<style lang="scss" scoped>
.query-editor-page {
    width: 100%;
    height: 100%;
}
</style>

Connection cleans up

This package does not automatically clean up the opened connection when the mxs-query-editor component is destroyed. e.g. When leaving the page, the opened connections are kept.

If all connections belong to one MaxScale, use the below vuex action to clear all connections:

store.dispatch('queryConn/disconnectAll', { root: true })

If connections belongs to multiple MaxScale, use the below example to clear all connections of a MaxScale:

for (const { id = '' } of connections_of_a_maxscale) {
    commit(
        'queryEditorConfig/SET_AXIOS_OPTS',
        {
            baseURL: maxscale_API_URL,
        },
        { root: true }
    )
    await dispatch('disconnect', { showSnackbar: false, id })
}

Build the editor

The query editor internally uses monaco-editor and it requires configuration steps from webpack.

//vue.config.js
const monacoConfig = require('mxs-query-editor/dist/buildConfig/monaco.js')
module.exports = {
    chainWebpack: config => {
        config
            .plugin('MonacoWebpackPlugin')
            .use(require('monaco-editor-webpack-plugin'), [monacoConfig])
    },
}

Change axios request config options

Axios request config options can be changed at run time by committing the following mutation:

store.commit('queryEditorConfig/SET_AXIOS_OPTS', options)

The provided config options will be merged with the current one which has the following default options:

{
    baseURL: '/',
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
   },
}

Check axios documentation for available options

Change authentication cookies expired time

The default expired time for the authentication cookies of SQL connections is 24 hours (86400). To change it, committing the following mutation:

store.commit('queryEditorConfig/SET_AUTH_COOKIES_MAX_AGE', 86400)

Reserved keywords

Certain keywords are reserved in order to make the query editor work properly.

| Keywords | For | | ------------------ | :------------------------------------------------: | | queryEditor | i18n json locale | | mxs_icon_name | Query editor icons, they have mxs_as the prefix. | | mxs-component-name | Global Vue components withmxs-as the prefix | | mxs-query-editor | Global Vue component | | mxsApp | Vuex module | | wke | Vuex module | | queryConn | Vuex module | | editor | Vuex module | | schemaSidebar | Vuex module | | queryResult | Vuex module | | querySession | Vuex module | | queryPersisted | Vuex module | | queryEditorConfig | Vuex module | | store.vue | Vuex store | | $mxs_t | Vue instance property | | $mxs_tc | Vue instance property | | $mxs_te | Vue instance property | | $mxs_d | Vue instance property | | $mxs_n | Vue instance property | | $queryHttp | Vue instance property | | $helpers | Vue instance property | | $logger | Vue instance property |

How to publish the package

At the root directory that is /maxgui

npm ci && cd queryEditor/package && npm ci --force && npm publish