feat: locales remote fetch+ deps update + fixes

This commit is contained in:
NGPixel 2018-04-29 17:55:36 -04:00
parent 3752cf7415
commit 7786f9042f
30 changed files with 1374 additions and 1106 deletions

View File

@ -34,12 +34,8 @@
</template> </template>
<script> <script>
import IconHomeAlert from 'mdi/home-alert'
export default { export default {
components: {
IconHomeAlert
},
data() { data() {
return { return {
siteTitle: 'Wiki.js', siteTitle: 'Wiki.js',

View File

@ -8,19 +8,35 @@
v-layout(row wrap) v-layout(row wrap)
v-flex(lg6 xs12) v-flex(lg6 xs12)
v-card v-card
v-toolbar(color='primary', dark, dense, flat) v-toolbar(color='grey darken-3', dark, dense, flat)
v-toolbar-title v-toolbar-title
.subheading Locale Settings .subheading Locale Settings
v-card-text v-card-text
v-select(:items='locales', prepend-icon='public', v-model='selectedLocale', label='Site Locale', persistent-hint, hint='All UI text elements will be displayed in selected language.') v-select(:items='installedLocales'
prepend-icon='public'
v-model='selectedLocale'
item-text='name'
label='Site Locale'
persistent-hint
hint='All UI text elements will be displayed in selected language.'
)
template(slot='item', slot-scope='data') template(slot='item', slot-scope='data')
template(v-if='typeof data.item !== "object"')
v-list-tile-content(v-text='data.item')
template(v-else)
v-list-tile-avatar v-list-tile-avatar
v-avatar.blue.white--text(tile, size='40', v-html='data.item.value.toUpperCase()') v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
v-list-tile-content v-list-tile-content
v-list-tile-title(v-html='data.item.text') v-list-tile-title(v-html='data.item.name')
v-list-tile-sub-title(v-html='data.item.original') v-list-tile-sub-title(v-html='data.item.nativeName')
v-divider v-divider
v-switch(v-model='rtlEnabled', label='RTL Display Mode', color='primary', persistent-hint, hint='For Right-to-Left languages, e.g. Arabic') v-switch(
v-model='autoUpdate'
label='Update Automatically'
color='primary'
persistent-hint
hint='Automatically download updates to this locale as they become available.'
)
v-divider v-divider
.px-3.pb-3 .px-3.pb-3
v-btn(color='primary') Save v-btn(color='primary') Save
@ -30,52 +46,46 @@
v-toolbar-title v-toolbar-title
.subheading Download Locale .subheading Download Locale
v-list v-list
v-list-tile(@click='') v-list-tile(v-for='lc in locales')
v-list-tile-avatar v-list-tile-avatar
v-avatar.teal.white--text(tile, size='40') ZH v-avatar.teal.white--text(tile, size='40') {{lc.code.toUpperCase()}}
v-list-tile-content v-list-tile-content
v-list-tile-title Chinese v-list-tile-title(v-html='lc.name')
v-list-tile-sub-title 中文 v-list-tile-sub-title(v-html='lc.nativeName')
v-list-tile-action v-list-tile-action(v-if='lc.isInstalled && lc.installDate < lc.updatedAt')
v-btn(icon) v-icon.blue--text cached
v-list-tile-action(v-else-if='lc.isInstalled')
v-icon.green--text check
v-list-tile-action(v-else)
v-btn(icon, @click='')
v-icon.grey--text cloud_download v-icon.grey--text cloud_download
v-list-tile(@click='')
v-list-tile-avatar
v-avatar.teal.white--text(tile, size='40') EN
v-list-tile-content
v-list-tile-title English
v-list-tile-sub-title English
v-list-tile-action
v-icon.green--text check
v-list-tile(@click='')
v-list-tile-avatar
v-avatar.teal.white--text(tile, size='40') FR
v-list-tile-content
v-list-tile-title French
v-list-tile-sub-title Français
v-list-tile-action
v-icon.green--text check
v-list-tile(@click='')
v-list-tile-avatar
v-avatar.teal.white--text(tile, size='40') RU
v-list-tile-content
v-list-tile-title Russian
v-list-tile-sub-title Русский
v-list-tile-action
v-btn(icon)
v-icon.blue--text update
</template> </template>
<script> <script>
import _ from 'lodash'
import localesQuery from 'gql/admin-locale-query-list.gql'
export default { export default {
data() { data() {
return { return {
locales: [ locales: [],
{ text: 'English', original: 'English', value: 'en' },
{ text: 'French', original: 'Français', value: 'fr' }
],
selectedLocale: 'en', selectedLocale: 'en',
rtlEnabled: false autoUpdate: true
}
},
computed: {
installedLocales() {
return _.filter(this.locales, ['isInstalled', true])
}
},
apollo: {
locales: {
query: localesQuery,
update: (data) => data.localization.locales,
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-locale-refresh')
}
} }
} }
} }

View File

@ -8,7 +8,7 @@
v-layout(row wrap) v-layout(row wrap)
v-flex(lg6 xs12) v-flex(lg6 xs12)
v-card v-card
v-toolbar(color='primary', dark, dense, flat) v-toolbar(color='grey darken-3', dark, dense, flat)
v-toolbar-title v-toolbar-title
.subheading Theme .subheading Theme
v-card-text v-card-text
@ -20,16 +20,16 @@
v-list-tile-title(v-html='data.item.text') v-list-tile-title(v-html='data.item.text')
v-list-tile-sub-title(v-html='data.item.author') v-list-tile-sub-title(v-html='data.item.author')
v-divider v-divider
v-switch(v-model='darkMode', label='Dark Mode', color='primary', persistent-hint, hint='Not recommended for accessibility') v-switch(v-model='darkMode', label='Dark Mode', color='primary', persistent-hint, hint='Not recommended for accessibility.')
v-divider v-divider
.px-3.pb-3 .px-3.pb-3
v-btn(color='primary') Save v-btn(color='primary') Save
v-flex(lg6 xs12) v-flex(lg6 xs12)
v-card v-card
v-toolbar(color='primary', dark, dense, flat) v-toolbar(color='teal', dark, dense, flat)
v-toolbar-title v-toolbar-title
.subheading --- .subheading Download Themes
v-card-text --- v-card-text.caption -- Coming soon --
</template> </template>
<script> <script>

View File

@ -14,7 +14,7 @@
v-layout(row, wrap) v-layout(row, wrap)
v-flex(xs12, sm6) v-flex(xs12, sm6)
v-card v-card
v-toolbar(color='primary', dark, dense, flat) v-toolbar(color='grey darken-3', dark, dense, flat)
v-toolbar-title v-toolbar-title
.subheading Authentication .subheading Authentication
v-subheader Flush User Sessions v-subheader Flush User Sessions
@ -31,14 +31,25 @@
span Proceed span Proceed
v-flex(xs12, sm6) v-flex(xs12, sm6)
v-card v-card
v-toolbar(color='primary', dark, dense, flat) v-toolbar(color='grey darken-3', dark, dense, flat)
v-toolbar-title v-toolbar-title
.subheading Maintenance Mode .subheading Maintenance Mode
v-card-text v-card-text
.body-1 Maintenance mode restrict access to the site to administrators only, regarless of current permissions. .body-1 Maintenance mode restrict access to the site to administrators only, regarless of current permissions.
v-btn.mt-3(color='orange darken-2', dark) v-btn.mt-3.ml-0(color='orange darken-2', depressed, dark)
icon-home-alert.mr-2(fillColor='#FFFFFF') icon-home-alert.mr-2(fillColor='#FFFFFF')
| Turn On Maintenance Mode | Turn On Maintenance Mode
v-card.mt-3
v-toolbar(color='grey darken-3', dark, dense, flat)
v-toolbar-title
.subheading Graph Endpoint
v-card-text
.body-1 The Graph API Endpoint from which remote resources like locales, themes and plugins are fetched.
.caption Do not change unless you know what you're doing!
v-text-field.my-2.grey.lighten-3(solo, flat, label='Graph Endpoint', value='https://graph.requarks.io')
v-btn.ml-0(color='primary', depressed, dark)
v-icon(left) chevron_right
span Save
v-tab-item(key='telemetry', :transition='false', :reverse-transition='false') v-tab-item(key='telemetry', :transition='false', :reverse-transition='false')
v-card.pa-3 v-card.pa-3
@ -110,10 +121,12 @@
<script> <script>
import IconGithubCircle from 'mdi/github-circle' import IconGithubCircle from 'mdi/github-circle'
import IconHomeAlert from 'mdi/home-alert'
export default { export default {
components: { components: {
IconGithubCircle IconGithubCircle,
IconHomeAlert
}, },
data() { data() {
return { return {

View File

@ -111,7 +111,7 @@
v-form v-form
v-container v-container
v-layout(row, wrap) v-layout(row, wrap)
v-flex(xs12) v-flex(xs12, sm6).pr-3
v-text-field( v-text-field(
v-model='conf.title', v-model='conf.title',
label='Site Title', label='Site Title',
@ -124,37 +124,7 @@
data-vv-scope='general', data-vv-scope='general',
:error-messages='errors.collect(`siteTitle`)' :error-messages='errors.collect(`siteTitle`)'
) )
v-layout(row, wrap).mt-3 v-flex.pr-3(xs12, sm6)
v-flex.pr-3(xs12, sm4)
v-select(
v-model='conf.lang',
:items='langs',
label='Site UI Language',
item-value='id',
item-text='name',
persistent-hint,
hint='The language in which navigation, help and other UI elements will be displayed.'
)
template(slot='item', slot-scope='data')
v-list-tile-avatar
v-avatar.blue.white--text(tile, size='40', v-html='data.item.id.toUpperCase()')
v-list-tile-content
v-list-tile-title(v-html='data.item.name')
v-list-tile-sub-title(v-html='data.item.original')
v-flex(xs12, sm8)
v-text-field(
v-model='conf.pathContent',
label='Content Data Path',
persistent-hint,
hint='The path where content is stored (markdown files, uploads, etc.)',
v-validate='{ required: true, min: 2 }',
data-vv-name='pathContent',
data-vv-as='Content Data Path',
data-vv-scope='general',
:error-messages='errors.collect(`pathContent`)'
)
v-layout(row, wrap).mt-3
v-flex.pr-3(xs12, sm4)
v-text-field( v-text-field(
v-model='conf.port', v-model='conf.port',
label='Server Port', label='Server Port',
@ -166,7 +136,20 @@
data-vv-scope='general', data-vv-scope='general',
:error-messages='errors.collect(`port`)' :error-messages='errors.collect(`port`)'
) )
v-flex(xs12, sm8) v-layout(row, wrap).mt-3
v-flex(xs12, sm6).pr-3
v-text-field(
v-model='conf.pathContent',
label='Content Data Path',
persistent-hint,
hint='The path where content is stored (markdown files, uploads, etc.)',
v-validate='{ required: true, min: 2 }',
data-vv-name='pathContent',
data-vv-as='Content Data Path',
data-vv-scope='general',
:error-messages='errors.collect(`pathContent`)'
)
v-flex(xs12, sm6)
v-text-field( v-text-field(
v-model='conf.pathData', v-model='conf.pathData',
label='Temporary Data Path', label='Temporary Data Path',

View File

@ -0,0 +1,14 @@
{
localization {
locales {
code
createdAt
isInstalled
installDate
isRTL
name
nativeName
updatedAt
}
}
}

View File

@ -76,4 +76,5 @@ workers: 0
ha: ha:
node: primary node: primary
uid: master
readonly: false readonly: false

View File

@ -2,6 +2,7 @@ const webpack = require('webpack')
const path = require('path') const path = require('path')
const fs = require('fs-extra') const fs = require('fs-extra')
const { VueLoaderPlugin } = require('vue-loader')
const CopyWebpackPlugin = require('copy-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin') const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin')
@ -73,6 +74,12 @@ module.exports = {
options: { options: {
sourceMap: false sourceMap: false
} }
},
{
loader: 'sass-resources-loader',
options: {
resources: path.join(process.cwd(), '/client/scss/global.scss')
}
} }
] ]
}, },
@ -87,43 +94,14 @@ module.exports = {
}, },
{ {
test: /\.vue$/, test: /\.vue$/,
loader: 'vue-loader', loader: 'vue-loader'
options: {
loaders: {
scss: [
'vue-style-loader',
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}, },
{ {
loader: 'sass-resources-loader', test: /\.pug$/,
options: { exclude: [
resources: path.join(process.cwd(), '/client/scss/global.scss') path.join(process.cwd(), 'dev')
}
}
], ],
js: [ loader: 'pug-plain-loader'
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
{
loader: 'babel-loader',
options: {
babelrc: path.join(process.cwd(), '.babelrc'),
cacheDirectory: babelDir
}
}
]
}
}
}, },
{ {
test: /\.(png|jpg|gif)$/, test: /\.(png|jpg|gif)$/,
@ -182,6 +160,7 @@ module.exports = {
] ]
}, },
plugins: [ plugins: [
new VueLoaderPlugin(),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
{ from: 'client/static' }, { from: 'client/static' },
{ from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' } { from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' }

View File

@ -11,6 +11,7 @@ const OfflinePlugin = require('offline-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin') const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin') const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc')) const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
const cacheDir = '.webpack-cache/cache' const cacheDir = '.webpack-cache/cache'
@ -26,8 +27,8 @@ module.exports = {
output: { output: {
path: path.join(process.cwd(), 'assets'), path: path.join(process.cwd(), 'assets'),
publicPath: '/', publicPath: '/',
filename: 'js/[name].js', filename: 'js/[name].[hash].js',
chunkFilename: 'js/[name].js', chunkFilename: 'js/[name].[chunkhash].js',
globalObject: 'this' globalObject: 'this'
}, },
module: { module: {
@ -78,6 +79,12 @@ module.exports = {
options: { options: {
sourceMap: false sourceMap: false
} }
},
{
loader: 'sass-resources-loader',
options: {
resources: path.join(process.cwd(), '/client/scss/global.scss')
}
} }
] ]
}, },
@ -93,44 +100,14 @@ module.exports = {
}, },
{ {
test: /\.vue$/, test: /\.vue$/,
loader: 'vue-loader', loader: 'vue-loader'
options: {
loaders: {
scss: [
'vue-style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}, },
{ {
loader: 'sass-resources-loader', test: /\.pug$/,
options: { exclude: [
resources: path.join(process.cwd(), '/client/scss/global.scss') path.join(process.cwd(), 'dev')
}
}
], ],
js: [ loader: 'pug-plain-loader'
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
{
loader: 'babel-loader',
options: {
babelrc: path.join(process.cwd(), '.babelrc'),
cacheDirectory: babelDir
}
}
]
}
}
}, },
{ {
test: /\.(png|jpg|gif)$/, test: /\.(png|jpg|gif)$/,
@ -189,19 +166,20 @@ module.exports = {
] ]
}, },
plugins: [ plugins: [
new VueLoaderPlugin(),
new webpack.BannerPlugin('Wiki.js - wiki.js.org - Licensed under AGPL'), new webpack.BannerPlugin('Wiki.js - wiki.js.org - Licensed under AGPL'),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
{ from: 'client/static' }, { from: 'client/static' },
{ from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' } { from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' }
], {}), ], {}),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: 'css/bundle.css', filename: 'css/bundle.[hash].css',
chunkFilename: 'css/[name].css' chunkFilename: 'css/[name].[chunkhash].css'
}), }),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
template: 'dev/templates/master.pug', template: 'dev/templates/master.pug',
filename: '../server/views/master.pug', filename: '../server/views/master.pug',
hash: true, hash: false,
inject: 'head' inject: 'head'
}), }),
new HtmlWebpackPugPlugin(), new HtmlWebpackPugPlugin(),

View File

@ -38,17 +38,17 @@
"node": ">=8.9.3" "node": ">=8.9.3"
}, },
"dependencies": { "dependencies": {
"apollo-server-express": "1.3.2", "apollo-server-express": "1.3.6",
"auto-load": "3.0.0", "auto-load": "3.0.0",
"axios": "0.18.0", "axios": "0.18.0",
"bcryptjs-then": "1.0.1", "bcryptjs-then": "1.0.1",
"bluebird": "3.5.1", "bluebird": "3.5.1",
"body-parser": "1.18.2", "body-parser": "1.18.2",
"bugsnag": "2.3.1", "bugsnag": "2.3.1",
"bull": "3.3.10", "bull": "3.4.1",
"cheerio": "1.0.0-rc.2", "cheerio": "1.0.0-rc.2",
"child-process-promise": "2.2.1", "child-process-promise": "2.2.1",
"chokidar": "2.0.2", "chokidar": "2.0.3",
"compression": "1.7.2", "compression": "1.7.2",
"connect-redis": "3.3.3", "connect-redis": "3.3.3",
"cookie-parser": "1.4.3", "cookie-parser": "1.4.3",
@ -66,18 +66,18 @@
"follow-redirects": "1.4.1", "follow-redirects": "1.4.1",
"fs-extra": "5.0.0", "fs-extra": "5.0.0",
"graphql": "0.13.2", "graphql": "0.13.2",
"graphql-list-fields": "2.0.1", "graphql-list-fields": "2.0.2",
"graphql-tools": "2.23.1", "graphql-tools": "3.0.0",
"i18next": "10.5.1", "i18next": "11.2.3",
"i18next-express-middleware": "1.1.1", "i18next-express-middleware": "1.1.1",
"i18next-localstorage-cache": "1.1.1", "i18next-localstorage-cache": "1.1.1",
"i18next-node-fs-backend": "1.0.0", "i18next-node-fs-backend": "1.0.0",
"image-size": "0.6.2", "image-size": "0.6.2",
"ioredis": "3.2.2", "ioredis": "3.2.2",
"js-yaml": "3.11.0", "js-yaml": "3.11.0",
"jsonwebtoken": "8.2.0", "jsonwebtoken": "8.2.1",
"klaw": "2.1.1", "klaw": "2.1.1",
"lodash": "4.17.5", "lodash": "4.17.10",
"markdown-it": "8.4.1", "markdown-it": "8.4.1",
"markdown-it-abbr": "1.0.4", "markdown-it-abbr": "1.0.4",
"markdown-it-anchor": "4.0.0", "markdown-it-anchor": "4.0.0",
@ -92,11 +92,11 @@
"markdown-it-sub": "1.0.0", "markdown-it-sub": "1.0.0",
"markdown-it-sup": "1.0.0", "markdown-it-sup": "1.0.0",
"markdown-it-task-lists": "2.1.1", "markdown-it-task-lists": "2.1.1",
"mathjax-node": "2.0.1", "mathjax-node": "2.1.0",
"mime-types": "2.1.18", "mime-types": "2.1.18",
"moment": "2.21.0", "moment": "2.22.1",
"moment-timezone": "0.5.14", "moment-timezone": "0.5.16",
"mongodb": "3.0.4", "mongodb": "3.0.7",
"multer": "1.3.0", "multer": "1.3.0",
"mysql2": "1.5.3", "mysql2": "1.5.3",
"node-2fa": "1.1.2", "node-2fa": "1.1.2",
@ -119,18 +119,18 @@
"pg": "6.4.2", "pg": "6.4.2",
"pg-hstore": "2.3.2", "pg-hstore": "2.3.2",
"pg-promise": "7.5.3", "pg-promise": "7.5.3",
"pm2": "2.10.1", "pm2": "2.10.3",
"pug": "2.0.1", "pug": "2.0.3",
"qr-image": "3.2.0", "qr-image": "3.2.0",
"raven": "2.4.2", "raven": "2.6.0",
"read-chunk": "2.1.0", "read-chunk": "2.1.0",
"remove-markdown": "0.2.2", "remove-markdown": "0.2.2",
"request": "2.85.0", "request": "2.85.0",
"request-promise": "4.2.2", "request-promise": "4.2.2",
"scim-query-filter-parser": "1.1.0", "scim-query-filter-parser": "1.1.0",
"semver": "5.5.0", "semver": "5.5.0",
"sequelize": "4.37.1", "sequelize": "4.37.6",
"serve-favicon": "2.4.5", "serve-favicon": "2.5.0",
"sqlite3": "4.0.0", "sqlite3": "4.0.0",
"uuid": "3.2.1", "uuid": "3.2.1",
"validator": "9.4.1", "validator": "9.4.1",
@ -140,14 +140,14 @@
}, },
"devDependencies": { "devDependencies": {
"@panter/vue-i18next": "0.9.1", "@panter/vue-i18next": "0.9.1",
"@vue/cli": "3.0.0-beta.6", "@vue/cli": "3.0.0-beta.9",
"apollo-client-preset": "1.0.8", "apollo-client-preset": "1.0.8",
"apollo-fetch": "0.7.0", "apollo-fetch": "0.7.0",
"apollo-link-batch-http": "1.2.1", "apollo-link-batch-http": "1.2.2",
"autoprefixer": "8.1.0", "autoprefixer": "8.3.0",
"babel-cli": "6.26.0", "babel-cli": "6.26.0",
"babel-core": "6.26.0", "babel-core": "6.26.3",
"babel-eslint": "8.2.2", "babel-eslint": "8.2.3",
"babel-jest": "23.0.0-alpha.0", "babel-jest": "23.0.0-alpha.0",
"babel-loader": "7.1.4", "babel-loader": "7.1.4",
"babel-plugin-graphql-tag": "1.5.0", "babel-plugin-graphql-tag": "1.5.0",
@ -164,74 +164,75 @@
"copy-webpack-plugin": "4.5.1", "copy-webpack-plugin": "4.5.1",
"css-loader": "0.28.11", "css-loader": "0.28.11",
"cssnano": "4.0.0-rc.2", "cssnano": "4.0.0-rc.2",
"duplicate-package-checker-webpack-plugin": "2.1.0", "duplicate-package-checker-webpack-plugin": "3.0.0",
"eslint": "4.19.0", "eslint": "4.19.1",
"eslint-config-requarks": "1.0.7", "eslint-config-requarks": "1.0.7",
"eslint-config-standard": "11.0.0", "eslint-config-standard": "11.0.0",
"eslint-plugin-import": "2.9.0", "eslint-plugin-import": "2.11.0",
"eslint-plugin-node": "6.0.1", "eslint-plugin-node": "6.0.1",
"eslint-plugin-promise": "3.7.0", "eslint-plugin-promise": "3.7.0",
"eslint-plugin-standard": "3.0.1", "eslint-plugin-standard": "3.1.0",
"eslint-plugin-vue": "4.3.0", "eslint-plugin-vue": "4.5.0",
"file-loader": "1.1.11", "file-loader": "1.1.11",
"graphiql": "0.11.11", "graphiql": "0.11.11",
"graphql-tag": "^2.8.0", "graphql-tag": "^2.9.1",
"graphql-voyager": "1.0.0-rc.15", "graphql-voyager": "1.0.0-rc.15",
"hammerjs": "2.0.8", "hammerjs": "2.0.8",
"html-webpack-plugin": "3.0.6", "html-webpack-plugin": "3.2.0",
"html-webpack-pug-plugin": "0.3.0", "html-webpack-pug-plugin": "0.3.0",
"i18next-xhr-backend": "1.5.1", "i18next-xhr-backend": "1.5.1",
"ignore-loader": "0.1.2", "ignore-loader": "0.1.2",
"jest": "22.4.2", "jest": "22.4.3",
"jest-junit": "3.6.0", "jest-junit": "3.7.0",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"lodash-webpack-plugin": "0.11.4", "lodash-webpack-plugin": "0.11.5",
"mini-css-extract-plugin": "0.2.0", "mini-css-extract-plugin": "0.4.0",
"node-sass": "4.7.2", "node-sass": "4.9.0",
"offline-plugin": "4.9.0", "offline-plugin": "5.0.1",
"optimize-css-assets-webpack-plugin": "4.0.0", "optimize-css-assets-webpack-plugin": "4.0.0",
"postcss-cssnext": "3.1.0", "postcss-cssnext": "3.1.0",
"postcss-flexbugs-fixes": "3.3.0", "postcss-flexbugs-fixes": "3.3.0",
"postcss-flexibility": "2.0.0", "postcss-flexibility": "2.0.0",
"postcss-import": "11.1.0", "postcss-import": "11.1.0",
"postcss-loader": "2.1.2", "postcss-loader": "2.1.4",
"postcss-selector-parser": "3.1.1", "postcss-selector-parser": "4.0.0",
"pug-lint": "2.5.0", "pug-lint": "2.5.0",
"pug-loader": "2.3.0", "pug-loader": "2.4.0",
"pug-plain-loader": "1.0.0",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"react": "16.2.0", "react": "16.3.2",
"react-dom": "16.2.0", "react-dom": "16.3.2",
"sass-loader": "6.0.7", "sass-loader": "7.0.1",
"sass-resources-loader": "1.3.3", "sass-resources-loader": "1.3.3",
"script-ext-html-webpack-plugin": "2.0.1", "script-ext-html-webpack-plugin": "2.0.1",
"simple-progress-webpack-plugin": "1.1.2", "simple-progress-webpack-plugin": "1.1.2",
"style-loader": "0.20.3", "style-loader": "0.21.0",
"stylus": "0.54.5", "stylus": "0.54.5",
"stylus-loader": "3.0.2", "stylus-loader": "3.0.2",
"twemoji-awesome": "1.0.6", "twemoji-awesome": "1.0.6",
"vee-validate": "2.0.5", "vee-validate": "2.0.8",
"velocity-animate": "1.5.1", "velocity-animate": "1.5.1",
"vue": "2.5.16", "vue": "2.5.16",
"vue-apollo": "3.0.0-beta.5", "vue-apollo": "3.0.0-beta.5",
"vue-clipboards": "1.2.2", "vue-clipboards": "1.2.4",
"vue-codemirror": "4.0.3", "vue-codemirror": "4.0.5",
"vue-hot-reload-api": "2.3.0", "vue-hot-reload-api": "2.3.0",
"vue-loader": "14.2.1", "vue-loader": "15.0.4",
"vue-material-design-icons": "1.2.1", "vue-material-design-icons": "1.4.0",
"vue-moment": "3.2.0", "vue-moment": "3.2.0",
"vue-router": "3.0.1", "vue-router": "3.0.1",
"vue-simple-breakpoints": "1.0.3", "vue-simple-breakpoints": "1.0.3",
"vue-template-compiler": "2.5.16", "vue-template-compiler": "2.5.16",
"vuetify": "1.0.8", "vuetify": "1.0.17",
"vuex": "3.0.1", "vuex": "3.0.1",
"vuex-persistedstate": "2.5.1", "vuex-persistedstate": "2.5.2",
"webpack": "4.1.1", "webpack": "4.6.0",
"webpack-bundle-analyzer": "2.11.1", "webpack-bundle-analyzer": "2.11.1",
"webpack-cli": "2.0.12", "webpack-cli": "2.0.15",
"webpack-dev-middleware": "3.0.1", "webpack-dev-middleware": "3.1.3",
"webpack-hot-middleware": "2.21.2", "webpack-hot-middleware": "2.22.1",
"webpack-merge": "4.1.2", "webpack-merge": "4.1.2",
"whatwg-fetch": "2.0.3", "whatwg-fetch": "2.0.4",
"write-file-webpack-plugin": "4.2.0" "write-file-webpack-plugin": "4.2.0"
}, },
"browserslist": [ "browserslist": [

View File

@ -27,6 +27,7 @@ defaults:
workers: 0 workers: 0
ha: ha:
node: primary node: primary
uid: master
readonly: false readonly: false
# DB defaults # DB defaults
auth: auth:
@ -62,88 +63,16 @@ configNamespaces:
localeNamespaces: localeNamespaces:
- auth - auth
- common - common
queues: jobs:
- gitSync purgeUploads:
- uplClearTemp onInit: true
cron: '*/15 * * * *'
syncGraphLocales:
onInit: true
cron: '0 0 * * *'
telemetry: telemetry:
BUGSNAG_ID: 'bb4b324d0675bcbba10025617fd2cec8' BUGSNAG_ID: 'bb4b324d0675bcbba10025617fd2cec8'
BUGSNAG_REMOTE: 'https://notify.bugsnag.com' BUGSNAG_REMOTE: 'https://notify.bugsnag.com'
GA_ID: 'UA-9094100-7' GA_ID: 'UA-9094100-7'
GA_REMOTE: 'https://www.google-analytics.com/collect' GA_REMOTE: 'https://www.google-analytics.com/collect'
authProviders:
- local
- microsoft
- google
- facebook
- github
- slack
- ldap
- azure
colors:
- red
- pink
- purple
- deep-purple
- indigo
- blue
- light-blue
- cyan
- teal
- green
- light-green
- lime
- yellow
- amber
- orange
- deep-orange
- brown
- grey
- blue-grey
langs:
-
id: en
name: English
original: English
-
id: zh
name: Chinese
original: 中文
-
id: nl
name: Dutch
original: Nederlands
-
id: fr
name: French
original: Français
-
id: de
name: German
original: Deutsch
-
id: ja
name: Japanese
original: 日本語
-
id: ko
name: Korean
original: 한국어
-
id: fa
name: Persian (Fārsi)
original: فارسی
-
id: pt
name: Portuguese
original: Português
-
id: ru
name: Russian
original: Русский
-
id: es
name: Spanish
original: Español
rtlLangs:
- fa
# --------------------------------- # ---------------------------------

View File

@ -10,7 +10,7 @@ module.exports = {
init() { init() {
if (cluster.isMaster) { if (cluster.isMaster) {
WIKI.logger.info('=======================================') WIKI.logger.info('=======================================')
WIKI.logger.info('= WIKI.js =============================') WIKI.logger.info('= Wiki.js =============================')
WIKI.logger.info('=======================================') WIKI.logger.info('=======================================')
WIKI.redis = require('./redis').init() WIKI.redis = require('./redis').init()
@ -55,13 +55,7 @@ module.exports = {
async postBootMaster() { async postBootMaster() {
await require('../master')() await require('../master')()
_.times(this.numWorkers, () => { WIKI.queue.start()
this.spawnWorker()
})
WIKI.queue.uplClearTemp.add({}, {
repeat: { cron: '*/15 * * * *' }
})
cluster.on('exit', (worker, code, signal) => { cluster.on('exit', (worker, code, signal) => {
if (!global.DEV) { if (!global.DEV) {

View File

@ -1,9 +1,7 @@
const _ = require('lodash') const _ = require('lodash')
const dotize = require('dotize') const dotize = require('dotize')
const i18nBackend = require('i18next-node-fs-backend')
const i18nMW = require('i18next-express-middleware') const i18nMW = require('i18next-express-middleware')
const i18next = require('i18next') const i18next = require('i18next')
const path = require('path')
const Promise = require('bluebird') const Promise = require('bluebird')
/* global WIKI */ /* global WIKI */
@ -14,17 +12,14 @@ module.exports = {
init() { init() {
this.namespaces = WIKI.data.localeNamespaces this.namespaces = WIKI.data.localeNamespaces
this.engine = i18next this.engine = i18next
this.engine.use(i18nBackend).init({ this.engine.init({
load: 'languageOnly', load: 'languageOnly',
ns: this.namespaces, ns: this.namespaces,
defaultNS: 'common', defaultNS: 'common',
saveMissing: false, saveMissing: false,
preload: [WIKI.config.site.lang], preload: [WIKI.config.site.lang],
lng: WIKI.config.site.lang, lng: WIKI.config.site.lang,
fallbackLng: 'en', fallbackLng: 'en'
backend: {
loadPath: path.join(WIKI.SERVERPATH, 'locales/{{lng}}/{{ns}}.yml')
}
}) })
return this return this
}, },

View File

@ -1,17 +1,16 @@
const _ = require('lodash') const _ = require('lodash')
const cluster = require('cluster')
const winston = require('winston') const winston = require('winston')
/* global WIKI */ /* global WIKI */
module.exports = { module.exports = {
loggers: {}, loggers: {},
init() { init(uid) {
let logger = winston.createLogger({ let logger = winston.createLogger({
level: WIKI.config.logLevel, level: WIKI.config.logLevel,
format: winston.format.combine( format: winston.format.combine(
winston.format.colorize(), winston.format.colorize(),
winston.format.label({ label: (cluster.isMaster) ? 'MASTER' : `WORKER-${cluster.worker.id}` }), winston.format.label({ label: uid }),
winston.format.timestamp(), winston.format.timestamp(),
winston.format.printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`) winston.format.printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`)
) )

View File

@ -1,23 +1,40 @@
const path = require('path')
const Bull = require('bull') const Bull = require('bull')
const Promise = require('bluebird') const Promise = require('bluebird')
const _ = require('lodash')
/* global WIKI */ /* global WIKI */
module.exports = { module.exports = {
job: {},
init() { init() {
WIKI.data.queues.forEach(queueName => { _.forOwn(WIKI.data.jobs, (queueParams, queueName) => {
this[queueName] = new Bull(queueName, { this.job[queueName] = new Bull(queueName, {
prefix: `q-${WIKI.config.ha.nodeuid}`, prefix: `q-${WIKI.config.ha.uid}`,
redis: WIKI.config.redis redis: WIKI.config.redis
}) })
this.job[queueName].process(path.join(WIKI.SERVERPATH, `jobs/${_.kebabCase(queueName)}.js`))
}) })
return this return this
}, },
clean() { start() {
return Promise.each(WIKI.data.queues, queueName => { _.forOwn(WIKI.data.jobs, (queueParams, queueName) => {
if (queueParams.onInit) {
this.job[queueName].add({}, {
removeOnComplete: true
})
}
this.job[queueName].add({}, {
repeat: { cron: queueParams.cron },
removeOnComplete: true
})
})
},
async clean() {
return Promise.each(_.keys(WIKI.data.jobs), queueName => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let keyStream = WIKI.redis.scanStream({ let keyStream = WIKI.redis.scanStream({
match: `q-${WIKI.config.ha.nodeuid}:${queueName}:*` match: `q-${WIKI.config.ha.uid}:${queueName}:*`
}) })
keyStream.on('data', resultKeys => { keyStream.on('data', resultKeys => {
if (resultKeys.length > 0) { if (resultKeys.length > 0) {

18
server/core/worker.js Normal file
View File

@ -0,0 +1,18 @@
const path = require('path')
let WIKI = {
IS_DEBUG: process.env.NODE_ENV === 'development',
ROOTPATH: process.cwd(),
SERVERPATH: path.join(process.cwd(), 'server'),
Error: require('../helpers/error'),
configSvc: require('./config')
}
global.WIKI = WIKI
WIKI.configSvc.init()
// ----------------------------------------
// Init Logger
// ----------------------------------------
WIKI.logger = require('./logger').init('JOB')

View File

@ -0,0 +1,46 @@
const graphHelper = require('../../helpers/graph')
const _ = require('lodash')
/* global WIKI */
module.exports = {
Query: {
async localization() { return {} }
},
Mutation: {
async localization() { return {} }
},
LocalizationQuery: {
async locales(obj, args, context, info) {
let remoteLocales = await WIKI.redis.get('locales')
let localLocales = await WIKI.db.Locale.findAll({
attributes: {
exclude: ['strings']
},
raw: true
})
remoteLocales = (remoteLocales) ? JSON.parse(remoteLocales) : localLocales
return _.map(remoteLocales, rl => {
let isInstalled = _.some(localLocales, ['code', rl.code])
return {
...rl,
isInstalled,
installDate: isInstalled ? _.find(localLocales, ['code', rl.code]).updatedAt : null
}
})
}
},
LocalizationMutation: {
async updateLocale(obj, args, context) {
try {
let authResult = await WIKI.db.User.login(args, context)
return {
...authResult,
responseResult: graphHelper.generateSuccess('Login success')
}
} catch (err) {
return graphHelper.generateError(err)
}
}
}
}

View File

@ -0,0 +1,45 @@
# ===============================================
# LOCALIZATION
# ===============================================
extend type Query {
localization: LocalizationQuery
}
extend type Mutation {
localization: LocalizationMutation
}
# -----------------------------------------------
# QUERIES
# -----------------------------------------------
type LocalizationQuery {
locales: [LocalizationLocale]
}
# -----------------------------------------------
# MUTATIONS
# -----------------------------------------------
type LocalizationMutation {
updateLocale(
localeId: String!
autoUpdate: Boolean!
): DefaultResponse
}
# -----------------------------------------------
# TYPES
# -----------------------------------------------
type LocalizationLocale {
code: String!
createdAt: Date!
installDate: Date
isInstalled: Boolean!
isRTL: Boolean!
name: String!
nativeName: String!
updatedAt: Date!
}

View File

@ -23,7 +23,7 @@ WIKI.configSvc.init()
// Init Logger // Init Logger
// ---------------------------------------- // ----------------------------------------
WIKI.logger = require('./core/logger').init() WIKI.logger = require('./core/logger').init('MASTER')
// ---------------------------------------- // ----------------------------------------
// Init Telemetry // Init Telemetry

View File

@ -0,0 +1,33 @@
require('../core/worker')
/* global WIKI */
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs-extra'))
const moment = require('moment')
const path = require('path')
module.exports = async (job) => {
WIKI.logger.info('Purging orphaned upload files...')
try {
const uplTempPath = path.resolve(process.cwd(), WIKI.config.paths.data, 'temp-upload')
const ls = await fs.readdirAsync(uplTempPath)
const fifteenAgo = moment().subtract(15, 'minutes')
await Promise.map(ls, (f) => {
return fs.statAsync(path.join(uplTempPath, f)).then((s) => { return { filename: f, stat: s } })
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
return Promise.map(arrFiles, (f) => {
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
return fs.unlinkAsync(path.join(uplTempPath, f.filename))
}
})
})
WIKI.logger.info('Purging orphaned upload files: [ COMPLETED ]')
} catch (err) {
WIKI.logger.error('Purging orphaned upload files: [ FAILED ]')
WIKI.logger.error(err.message)
}
}

69
server/jobs/sync-git.js Normal file
View File

@ -0,0 +1,69 @@
'use strict'
// /* global WIKI */
// const Promise = require('bluebird')
// const fs = Promise.promisifyAll(require('fs-extra'))
// const klaw = require('klaw')
// const moment = require('moment')
// const path = require('path')
// const entryHelper = require('../helpers/entry')
module.exports = (job) => {
return true
// return WIKI.git.resync().then(() => {
// // -> Stream all documents
// let cacheJobs = []
// let jobCbStreamDocsResolve = null
// let jobCbStreamDocs = new Promise((resolve, reject) => {
// jobCbStreamDocsResolve = resolve
// })
// klaw(WIKI.REPOPATH).on('data', function (item) {
// if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
// let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
// let cachePath = entryHelper.getCachePath(entryPath)
// // -> Purge outdated cache
// cacheJobs.push(
// fs.statAsync(cachePath).then((st) => {
// return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
// }).catch((err) => {
// return (err.code !== 'EEXIST') ? err : 'new'
// }).then((fileStatus) => {
// // -> Delete expired cache file
// if (fileStatus === 'expired') {
// return fs.unlinkAsync(cachePath).return(fileStatus)
// }
// return fileStatus
// }).then((fileStatus) => {
// // -> Update cache and search index
// if (fileStatus !== 'active') {
// return global.entries.updateCache(entryPath).then(entry => {
// process.send({
// action: 'searchAdd',
// content: entry
// })
// return true
// })
// }
// return true
// })
// )
// }
// }).on('end', () => {
// jobCbStreamDocsResolve(Promise.all(cacheJobs))
// })
// return jobCbStreamDocs
// }).then(() => {
// WIKI.logger.info('Git remote repository sync: DONE')
// return true
// })
}

View File

@ -0,0 +1,38 @@
require('../core/worker')
const _ = require('lodash')
const { createApolloFetch } = require('apollo-fetch')
/* global WIKI */
WIKI.redis = require('../core/redis').init()
const apollo = createApolloFetch({
uri: 'https://graph.requarks.io'
})
module.exports = async (job) => {
WIKI.logger.info('Syncing locales with Graph endpoint...')
try {
const resp = await apollo({
query: `{
localization {
locales {
code
name
nativeName
isRTL
createdAt
updatedAt
}
}
}`
})
const locales = _.sortBy(_.get(resp, 'data.localization.locales', []), 'name').map(lc => ({...lc, isInstalled: (lc.code === 'en')}))
WIKI.redis.set('locales', JSON.stringify(locales))
WIKI.logger.info('Syncing locales with Graph endpoint: [ COMPLETED ]')
} catch (err) {
WIKI.logger.error('Syncing locales with Graph endpoint: [ FAILED ]')
WIKI.logger.error(err.message)
}
}

View File

@ -0,0 +1,38 @@
{
"auth": {
"actions": {
"login": "Log In"
},
"errors": {
"invalidLogin": "Invalid Login",
"invalidLoginMsg": "The email or password is invalid.",
"invalidUserEmail": "Invalid User Email",
"loginError": "Login error",
"notYetAuthorized": "You have not been authorized to login to this site yet.",
"tooManyAttempts": "Too many attempts!",
"tooManyAttemptsMsg": "You've made too many failed attempts in a short period of time, please try again {{time}}.",
"userNotFound": "User not found"
},
"fields": {
"emailUser": "Email / Username",
"password": "Password"
},
"loginRequired": "Login required",
"providers": {
"azure": "Azure Active Directory",
"facebook": "Facebook",
"github": "GitHub",
"google": "Google ID",
"ldap": "LDAP / Active Directory",
"local": "Local",
"slack": "Slack",
"windowslive": "Microsoft Account"
},
"tfa": {
"placeholder": "XXXXXX",
"subtitle": "Security code required:",
"title": "Two Factor Authentication",
"verifyToken": "Verify"
}
}
}

39
server/models/locale.js Normal file
View File

@ -0,0 +1,39 @@
/**
* Locale schema
*/
module.exports = (sequelize, DataTypes) => {
let localeSchema = sequelize.define('locale', {
code: {
type: DataTypes.STRING,
allowNull: false
},
strings: {
type: DataTypes.JSON,
allowNull: true
},
isRTL: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
name: {
type: DataTypes.STRING,
allowNull: false
},
nativeName: {
type: DataTypes.STRING,
allowNull: false
}
}, {
timestamps: true,
version: true,
indexes: [
{
unique: true,
fields: ['code']
}
]
})
return localeSchema
}

View File

@ -1,68 +0,0 @@
'use strict'
/* global WIKI */
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs-extra'))
const klaw = require('klaw')
const moment = require('moment')
const path = require('path')
const entryHelper = require('../helpers/entry')
module.exports = (job) => {
return WIKI.git.resync().then(() => {
// -> Stream all documents
let cacheJobs = []
let jobCbStreamDocsResolve = null
let jobCbStreamDocs = new Promise((resolve, reject) => {
jobCbStreamDocsResolve = resolve
})
klaw(WIKI.REPOPATH).on('data', function (item) {
if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
let cachePath = entryHelper.getCachePath(entryPath)
// -> Purge outdated cache
cacheJobs.push(
fs.statAsync(cachePath).then((st) => {
return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
}).catch((err) => {
return (err.code !== 'EEXIST') ? err : 'new'
}).then((fileStatus) => {
// -> Delete expired cache file
if (fileStatus === 'expired') {
return fs.unlinkAsync(cachePath).return(fileStatus)
}
return fileStatus
}).then((fileStatus) => {
// -> Update cache and search index
if (fileStatus !== 'active') {
return global.entries.updateCache(entryPath).then(entry => {
process.send({
action: 'searchAdd',
content: entry
})
return true
})
}
return true
})
)
}
}).on('end', () => {
jobCbStreamDocsResolve(Promise.all(cacheJobs))
})
return jobCbStreamDocs
}).then(() => {
WIKI.logger.info('Git remote repository sync: DONE')
return true
})
}

View File

@ -1,29 +0,0 @@
'use strict'
/* global WIKI */
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs-extra'))
const moment = require('moment')
const path = require('path')
module.exports = (job) => {
return fs.readdirAsync(WIKI.UPLTEMPPATH).then((ls) => {
let fifteenAgo = moment().subtract(15, 'minutes')
return Promise.map(ls, (f) => {
return fs.statAsync(path.join(WIKI.UPLTEMPPATH, f)).then((s) => { return { filename: f, stat: s } })
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
return Promise.map(arrFiles, (f) => {
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
return fs.unlinkAsync(path.join(WIKI.UPLTEMPPATH, f.filename))
} else {
return true
}
})
})
}).then(() => {
WIKI.logger.info('Purging temporary upload files: DONE')
return true
})
}

View File

@ -283,7 +283,7 @@ module.exports = () => {
// Site namespace // Site namespace
_.set(WIKI.config.site, 'title', req.body.title) _.set(WIKI.config.site, 'title', req.body.title)
_.set(WIKI.config.site, 'lang', req.body.lang) _.set(WIKI.config.site, 'lang', 'en')
_.set(WIKI.config.site, 'rtl', _.includes(WIKI.data.rtlLangs, req.body.lang)) _.set(WIKI.config.site, 'rtl', _.includes(WIKI.data.rtlLangs, req.body.lang))
_.set(WIKI.config.site, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex')) _.set(WIKI.config.site, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex'))
@ -310,6 +310,16 @@ module.exports = () => {
tfaIsActive: false tfaIsActive: false
}) })
// Create default locale
WIKI.logger.info('Installing default locale...')
await WIKI.db.Locale.upsert({
code: 'en',
strings: require('./locales/default.json'),
isRTL: false,
name: 'English',
nativeName: 'English'
})
WIKI.logger.info('Setup is complete!') WIKI.logger.info('Setup is complete!')
res.json({ res.json({
ok: true, ok: true,

View File

@ -3,4 +3,4 @@ extends ../master.pug
block body block body
body body
#app #app
setup(telemetry-id=telemetryClientID, wiki-version=packageObj.version, :langs!=JSON.stringify(data.langs).replace(/"/g, "'")) setup(telemetry-id=telemetryClientID, wiki-version=packageObj.version)

View File

@ -1,62 +0,0 @@
const Promise = require('bluebird')
/* global WIKI */
module.exports = Promise.join(
WIKI.db.onReady,
WIKI.configSvc.loadFromDb(['features', 'logging', 'site', 'uploads'])
).then(() => {
const path = require('path')
WIKI.REPOPATH = path.resolve(WIKI.ROOTPATH, WIKI.config.paths.repo)
WIKI.DATAPATH = path.resolve(WIKI.ROOTPATH, WIKI.config.paths.data)
WIKI.UPLTEMPPATH = path.join(WIKI.DATAPATH, 'temp-upload')
// ----------------------------------------
// Load global modules
// ----------------------------------------
WIKI.lang = require('i18next')
// ----------------------------------------
// Localization Engine
// ----------------------------------------
const i18nBackend = require('i18next-node-fs-backend')
WIKI.lang.use(i18nBackend).init({
load: 'languageOnly',
ns: ['common', 'admin', 'auth', 'errors'],
defaultNS: 'common',
saveMissing: false,
preload: [WIKI.config.lang],
lng: WIKI.config.lang,
fallbackLng: 'en',
backend: {
loadPath: path.join(WIKI.SERVERPATH, 'locales/{{lng}}/{{ns}}.yml')
}
})
// ----------------------------------------
// Start Queues
// ----------------------------------------
const Bull = require('bull')
const autoload = require('auto-load')
let queues = autoload(path.join(WIKI.SERVERPATH, 'queues'))
for (let queueName in queues) {
new Bull(queueName, {
prefix: `q-${WIKI.config.ha.nodeuid}`,
redis: WIKI.config.redis
}).process(queues[queueName])
}
// ----------------------------------------
// Shutdown gracefully
// ----------------------------------------
process.on('disconnect', () => {
process.exit()
})
})

1416
yarn.lock

File diff suppressed because it is too large Load Diff