feat: extensions check + resolver
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
v-expansion-panel-header(disable-icon-rotate)
|
v-expansion-panel-header(disable-icon-rotate)
|
||||||
span {{ext.title}}
|
span {{ext.title}}
|
||||||
template(v-slot:actions)
|
template(v-slot:actions)
|
||||||
v-chip(label, color='success', small, v-if='ext.installed') Installed
|
v-chip(label, color='success', small, v-if='ext.isInstalled') Installed
|
||||||
v-chip(label, color='warning', small, v-else) Not Installed
|
v-chip(label, color='warning', small, v-else) Not Installed
|
||||||
v-expansion-panel-content.pa-0
|
v-expansion-panel-content.pa-0
|
||||||
v-card(flat, :class='$vuetify.theme.dark ? `grey darken-3` : `grey lighten-5`', tile)
|
v-card(flat, :class='$vuetify.theme.dark ? `grey darken-3` : `grey lighten-5`', tile)
|
||||||
@@ -25,18 +25,15 @@
|
|||||||
.body-2 {{ext.description}}
|
.body-2 {{ext.description}}
|
||||||
v-divider.my-4
|
v-divider.my-4
|
||||||
.body-2
|
.body-2
|
||||||
strong.mr-3 Supported Platforms:
|
strong.mr-2 This extensions is
|
||||||
v-chip.mr-1(label, small, :color='ext.platforms[`linux-amd64`] ? `success` : `error`') Linux (x64)
|
v-chip.mr-2(v-if='ext.isCompatible', label, outlined, small, color='success') compatible
|
||||||
v-chip.mr-1(label, small, :color='ext.platforms[`linux-arm64`] ? `success` : `error`') Linux (arm64)
|
v-chip.mr-2(v-else, label, small, color='error') not compatible
|
||||||
v-chip.mr-1(label, small, :color='ext.platforms[`linux-armv7`] ? `success` : `error`') Linux (armv7)
|
strong with your host.
|
||||||
v-chip.mr-1(label, small, :color='ext.platforms.macos ? `success` : `error`') MacOS
|
|
||||||
v-chip.mr-1(label, small, :color='ext.platforms.windows ? `success` : `error`') Windows
|
|
||||||
v-card-chin
|
v-card-chin
|
||||||
v-spacer
|
v-spacer
|
||||||
v-btn(disabled)
|
v-btn(disabled)
|
||||||
v-icon(left) mdi-plus
|
v-icon(left) mdi-plus
|
||||||
span Install
|
span Install
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -46,122 +43,70 @@ import gql from 'graphql-tag'
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: {},
|
extensions: []
|
||||||
extensions: [
|
|
||||||
{
|
|
||||||
key: 'git',
|
|
||||||
title: 'Git',
|
|
||||||
description: 'Distributed version control system. Required for the Git storage module.',
|
|
||||||
platforms: {
|
|
||||||
'linux-amd64': true,
|
|
||||||
'linux-arm64': true,
|
|
||||||
'linux-armv7': true,
|
|
||||||
'macos': true,
|
|
||||||
'windows': true
|
|
||||||
},
|
|
||||||
installed: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'pandoc',
|
|
||||||
title: 'Pandoc',
|
|
||||||
description: 'Convert between markup formats. Required for converting from other formats such as MediaWiki, AsciiDoc, Textile and other wikis.',
|
|
||||||
platforms: {
|
|
||||||
'linux-amd64': true,
|
|
||||||
'linux-arm64': false,
|
|
||||||
'linux-armv7': false,
|
|
||||||
'macos': true,
|
|
||||||
'windows': true
|
|
||||||
},
|
|
||||||
installed: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'puppeteer',
|
|
||||||
title: 'Puppeteer',
|
|
||||||
description: 'Headless chromium browser for server-side rendering. Required for generating PDF versions of pages and render content elements on the server (e.g. Mermaid diagrams)',
|
|
||||||
platforms: {
|
|
||||||
'linux-amd64': true,
|
|
||||||
'linux-arm64': false,
|
|
||||||
'linux-armv7': false,
|
|
||||||
'macos': true,
|
|
||||||
'windows': true
|
|
||||||
},
|
|
||||||
installed: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sharp',
|
|
||||||
title: 'Sharp',
|
|
||||||
description: 'Process and transform images. Required to generate thumbnails of uploaded images and perform transformations.',
|
|
||||||
platforms: {
|
|
||||||
'linux-amd64': true,
|
|
||||||
'linux-arm64': false,
|
|
||||||
'linux-armv7': false,
|
|
||||||
'macos': true,
|
|
||||||
'windows': true
|
|
||||||
},
|
|
||||||
installed: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
async save () {
|
async save () {
|
||||||
try {
|
// try {
|
||||||
await this.$apollo.mutate({
|
// await this.$apollo.mutate({
|
||||||
mutation: gql`
|
// mutation: gql`
|
||||||
mutation (
|
// mutation (
|
||||||
$host: String!
|
// $host: String!
|
||||||
) {
|
// ) {
|
||||||
site {
|
// site {
|
||||||
updateConfig(
|
// updateConfig(
|
||||||
host: $host
|
// host: $host
|
||||||
) {
|
// ) {
|
||||||
responseResult {
|
// responseResult {
|
||||||
succeeded
|
// succeeded
|
||||||
errorCode
|
// errorCode
|
||||||
slug
|
// slug
|
||||||
message
|
// message
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// `,
|
||||||
|
// variables: {
|
||||||
|
// host: _.get(this.config, 'host', '')
|
||||||
|
// },
|
||||||
|
// watchLoading (isLoading) {
|
||||||
|
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-extensions-update')
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// this.$store.commit('showNotification', {
|
||||||
|
// style: 'success',
|
||||||
|
// message: 'Configuration saved successfully.',
|
||||||
|
// icon: 'check'
|
||||||
|
// })
|
||||||
|
// } catch (err) {
|
||||||
|
// this.$store.commit('pushGraphError', err)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
apollo: {
|
||||||
|
extensions: {
|
||||||
|
query: gql`
|
||||||
|
{
|
||||||
|
system {
|
||||||
|
extensions {
|
||||||
|
key
|
||||||
|
title
|
||||||
|
description
|
||||||
|
isInstalled
|
||||||
|
isCompatible
|
||||||
}
|
}
|
||||||
`,
|
|
||||||
variables: {
|
|
||||||
host: _.get(this.config, 'host', '')
|
|
||||||
},
|
|
||||||
watchLoading (isLoading) {
|
|
||||||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
this.$store.commit('showNotification', {
|
`,
|
||||||
style: 'success',
|
fetchPolicy: 'network-only',
|
||||||
message: 'Configuration saved successfully.',
|
update: (data) => _.cloneDeep(data.system.extensions),
|
||||||
icon: 'check'
|
watchLoading (isLoading) {
|
||||||
})
|
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-extensions-refresh')
|
||||||
} catch (err) {
|
|
||||||
this.$store.commit('pushGraphError', err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// apollo: {
|
|
||||||
// config: {
|
|
||||||
// query: gql`
|
|
||||||
// {
|
|
||||||
// site {
|
|
||||||
// config {
|
|
||||||
// host
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// `,
|
|
||||||
// fetchPolicy: 'network-only',
|
|
||||||
// update: (data) => _.cloneDeep(data.site.config),
|
|
||||||
// watchLoading (isLoading) {
|
|
||||||
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-refresh')
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ const state = {
|
|||||||
view: false,
|
view: false,
|
||||||
post: false,
|
post: false,
|
||||||
manage: false
|
manage: false
|
||||||
}
|
},
|
||||||
|
commentsCount: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -103,10 +103,10 @@
|
|||||||
dark
|
dark
|
||||||
style='min-width: 50px; justify-content: center;'
|
style='min-width: 50px; justify-content: center;'
|
||||||
)
|
)
|
||||||
span 334
|
span {{commentsCount}}
|
||||||
.d-flex
|
.d-flex
|
||||||
v-btn.text-none(
|
v-btn.text-none(
|
||||||
@click='goToComments'
|
@click='goToComments()'
|
||||||
:color='$vuetify.theme.dark ? `pink` : `pink darken-3`'
|
:color='$vuetify.theme.dark ? `pink` : `pink darken-3`'
|
||||||
outlined
|
outlined
|
||||||
style='flex: 1 1 100%;'
|
style='flex: 1 1 100%;'
|
||||||
@@ -441,6 +441,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isAuthenticated: get('user/authenticated'),
|
isAuthenticated: get('user/authenticated'),
|
||||||
|
commentsCount: get('page/commentsCount'),
|
||||||
rating: {
|
rating: {
|
||||||
get () {
|
get () {
|
||||||
return 3.5
|
return 3.5
|
||||||
|
|||||||
+1
-1
@@ -57,6 +57,7 @@
|
|||||||
"cheerio": "1.0.0-rc.3",
|
"cheerio": "1.0.0-rc.3",
|
||||||
"chokidar": "3.4.0",
|
"chokidar": "3.4.0",
|
||||||
"clean-css": "4.2.3",
|
"clean-css": "4.2.3",
|
||||||
|
"command-exists": "1.2.9",
|
||||||
"compression": "1.7.4",
|
"compression": "1.7.4",
|
||||||
"connect-session-knex": "1.6.0",
|
"connect-session-knex": "1.6.0",
|
||||||
"cookie-parser": "1.4.5",
|
"cookie-parser": "1.4.5",
|
||||||
@@ -162,7 +163,6 @@
|
|||||||
"scim-query-filter-parser": "2.0.4",
|
"scim-query-filter-parser": "2.0.4",
|
||||||
"semver": "7.3.2",
|
"semver": "7.3.2",
|
||||||
"serve-favicon": "2.5.0",
|
"serve-favicon": "2.5.0",
|
||||||
"sharp": "0.25.2",
|
|
||||||
"simple-git": "2.4.0",
|
"simple-git": "2.4.0",
|
||||||
"solr-node": "1.2.1",
|
"solr-node": "1.2.1",
|
||||||
"sqlite3": "4.2.0",
|
"sqlite3": "4.2.0",
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
ext: {},
|
||||||
|
async init () {
|
||||||
|
const extDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/extensions'))
|
||||||
|
WIKI.logger.info(`Checking for installed optional extensions...`)
|
||||||
|
for (let dir of extDirs) {
|
||||||
|
WIKI.extensions.ext[dir] = require(path.join(WIKI.SERVERPATH, 'modules/extensions', dir, 'ext.js'))
|
||||||
|
const isInstalled = await WIKI.extensions.ext[dir].check()
|
||||||
|
if (isInstalled) {
|
||||||
|
WIKI.logger.info(`Optional extension ${dir} is installed. [ OK ]`)
|
||||||
|
} else {
|
||||||
|
WIKI.logger.info(`Optional extension ${dir} was not found on this system. [ SKIPPED ]`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,6 +40,7 @@ module.exports = {
|
|||||||
inbound: new EventEmitter(),
|
inbound: new EventEmitter(),
|
||||||
outbound: new EventEmitter()
|
outbound: new EventEmitter()
|
||||||
}
|
}
|
||||||
|
WIKI.extensions = require('./extensions')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
WIKI.logger.error(err)
|
WIKI.logger.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
@@ -76,6 +77,8 @@ module.exports = {
|
|||||||
await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
|
await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
|
||||||
await WIKI.models.storage.refreshTargetsFromDisk()
|
await WIKI.models.storage.refreshTargetsFromDisk()
|
||||||
|
|
||||||
|
await WIKI.extensions.init()
|
||||||
|
|
||||||
await WIKI.auth.activateStrategies()
|
await WIKI.auth.activateStrategies()
|
||||||
await WIKI.models.commentProviders.initProvider()
|
await WIKI.models.commentProviders.initProvider()
|
||||||
await WIKI.models.searchEngines.initEngine()
|
await WIKI.models.searchEngines.initEngine()
|
||||||
|
|||||||
@@ -34,7 +34,14 @@ module.exports = {
|
|||||||
result.push({ key, value })
|
result.push({ key, value })
|
||||||
}, [])
|
}, [])
|
||||||
},
|
},
|
||||||
async info() { return {} }
|
async info () { return {} },
|
||||||
|
async extensions () {
|
||||||
|
const exts = Object.values(WIKI.extensions.ext).map(ext => _.pick(ext, ['key', 'title', 'description', 'isInstalled']))
|
||||||
|
for (let ext of exts) {
|
||||||
|
ext.isCompatible = await WIKI.extensions.ext[ext.key].isCompatible()
|
||||||
|
}
|
||||||
|
return exts
|
||||||
|
}
|
||||||
},
|
},
|
||||||
SystemMutation: {
|
SystemMutation: {
|
||||||
async updateFlags (obj, args, context) {
|
async updateFlags (obj, args, context) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ extend type Mutation {
|
|||||||
type SystemQuery {
|
type SystemQuery {
|
||||||
flags: [SystemFlag] @auth(requires: ["manage:system"])
|
flags: [SystemFlag] @auth(requires: ["manage:system"])
|
||||||
info: SystemInfo
|
info: SystemInfo
|
||||||
|
extensions: [SystemExtension]! @auth(requires: ["manage:system"])
|
||||||
}
|
}
|
||||||
|
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
@@ -112,3 +113,11 @@ type SystemImportUsersResponseFailed {
|
|||||||
email: String
|
email: String
|
||||||
error: String
|
error: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemExtension {
|
||||||
|
key: String!
|
||||||
|
title: String!
|
||||||
|
description: String!
|
||||||
|
isInstalled: Boolean!
|
||||||
|
isCompatible: Boolean!
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ module.exports = class CommentProvider extends Model {
|
|||||||
const dbProviders = await WIKI.models.commentProviders.query()
|
const dbProviders = await WIKI.models.commentProviders.query()
|
||||||
|
|
||||||
// -> Fetch definitions from disk
|
// -> Fetch definitions from disk
|
||||||
const authDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/comments'))
|
const commentDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/comments'))
|
||||||
let diskProviders = []
|
let diskProviders = []
|
||||||
for (let dir of authDirs) {
|
for (let dir of commentDirs) {
|
||||||
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/comments', dir, 'definition.yml'), 'utf8')
|
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/comments', dir, 'definition.yml'), 'utf8')
|
||||||
diskProviders.push(yaml.safeLoad(def))
|
diskProviders.push(yaml.safeLoad(def))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
const cmdExists = require('command-exists')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
key: 'git',
|
||||||
|
title: 'Git',
|
||||||
|
description: 'Distributed version control system. Required for the Git storage module.',
|
||||||
|
isInstalled: false,
|
||||||
|
async isCompatible () {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async check () {
|
||||||
|
try {
|
||||||
|
await cmdExists('git')
|
||||||
|
this.isInstalled = true
|
||||||
|
} catch (err) {
|
||||||
|
this.isInstalled = false
|
||||||
|
}
|
||||||
|
return this.isInstalled
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const cmdExists = require('command-exists')
|
||||||
|
const os = require('os')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
key: 'pandoc',
|
||||||
|
title: 'Pandoc',
|
||||||
|
description: 'Convert between markup formats. Required for converting from other formats such as MediaWiki, AsciiDoc, Textile and other wikis.',
|
||||||
|
async isCompatible () {
|
||||||
|
return os.arch() === 'x64'
|
||||||
|
},
|
||||||
|
isInstalled: false,
|
||||||
|
async check () {
|
||||||
|
try {
|
||||||
|
await cmdExists('pandoc')
|
||||||
|
this.isInstalled = true
|
||||||
|
} catch (err) {
|
||||||
|
this.isInstalled = false
|
||||||
|
}
|
||||||
|
return this.isInstalled
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const cmdExists = require('command-exists')
|
||||||
|
const os = require('os')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
key: 'puppeteer',
|
||||||
|
title: 'Puppeteer',
|
||||||
|
description: 'Headless chromium browser for server-side rendering. Required for generating PDF versions of pages and render content elements on the server (e.g. Mermaid diagrams)',
|
||||||
|
async isCompatible () {
|
||||||
|
return os.arch() === 'x64'
|
||||||
|
},
|
||||||
|
isInstalled: false,
|
||||||
|
async check () {
|
||||||
|
try {
|
||||||
|
await cmdExists('pandoc')
|
||||||
|
this.isInstalled = true
|
||||||
|
} catch (err) {
|
||||||
|
this.isInstalled = false
|
||||||
|
}
|
||||||
|
return this.isInstalled
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const fs = require('fs-extra')
|
||||||
|
const os = require('os')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
key: 'sharp',
|
||||||
|
title: 'Sharp',
|
||||||
|
description: 'Process and transform images. Required to generate thumbnails of uploaded images and perform transformations.',
|
||||||
|
async isCompatible () {
|
||||||
|
return os.arch() === 'x64'
|
||||||
|
},
|
||||||
|
isInstalled: false,
|
||||||
|
async check () {
|
||||||
|
this.isInstalled = await fs.pathExists(path.join(WIKI.ROOTPATH, 'node_modules/sharp'))
|
||||||
|
return this.isInstalled
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user