Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/doveadm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { doveadm_arg_types,
doveadm_args_human_timestamp,
doveadm_args_query,
doveadm_args_usermask,
doveadm_flag_types } from '../lib/doveadm.js'
doveadm_flag_types } from '../lib/constants/doveadm.js'

export const doveadm = {

Expand Down
2 changes: 1 addition & 1 deletion data/settings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Dovecot settings. */

import { setting_types } from '../lib/settings.js'
import { setting_types } from '../lib/constants/settings.js'

export const settings = {

Expand Down
40 changes: 40 additions & 0 deletions lib/constants/doveadm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* List of Doveadm argument value types. */
export const doveadm_arg_types = {
ARRAY: 1,
BOOL: 2,
INTEGER: 3,
STRING: 4,
SEARCH_QUERY: 5, // Search query is an ARG_ARRAY
ISTREAM: 6,
}

/* List of Doveadm flag value types. */
export const doveadm_flag_types = {
NONE: 0,
USER: 1,
USERFILE: 2,
USERMASK: 4,
}

export const doveadm_args_query = {
example: ['mailbox', 'INBOX/myfoldertoo', 'savedbefore', 'since', '30d'],
positional: true,
type: doveadm_arg_types.SEARCH_QUERY,
text: `Search query to apply.`,
}

export const doveadm_args_usermask = {
example: 'username',
positional: true,
type: doveadm_arg_types.STRING,
text: `User Mask.`
}

export const doveadm_args_human_timestamp = `
Allowable formats:

* yyyy-mm-dd (non-UTC),
* IMAP date ("dd-mm-yyyy"; see [[rfc,3501]]) (non-UTC)
* IMAP date-time ("dd-mm-yyy HH:MM:SS +0000; see [[rfc,3501]]) (UTC supported)
* Unix timestamp (UTC supported)
* Interval ("n days", UTC supported)`
93 changes: 93 additions & 0 deletions lib/constants/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* List of Dovecot settings value types. */
export const setting_types = {
BOOLEAN: {
label: 'Boolean',
url: '[[link,settings_types_boolean]]',
default_required: true,
},
IPADDR: {
label: 'IP Address(es)',
url: '[[link,settings_types_ip]]',
// Default: empty
},
SIZE: {
label: 'Size',
url: '[[link,settings_types_size]]',
default_required: true,
},
STRING: {
label: 'String',
url: '[[link,settings_types_string]]'
// Default: empty
},
STRING_NOVAR: {
label: 'String Without Variables',
url: '[[link,settings_types_string_novar]]'
// Default: empty
},
/* This is a String entry, with specific allowable values. */
ENUM: {
label: 'String',
url: '[[link,settings_types_string]]',
enum_required: true,
},
TIME: {
label: 'Time',
url: '[[link,settings_types_time]]',
default_required: true,
},
TIME_MSECS: {
label: 'Time (milliseconds)',
url: '[[link,settings_types_time_msecs]]',
default_required: true,
},
UINT: {
label: 'Unsigned Integer',
url: '[[link,settings_types_uint]]',
default_required: true,
},
OCTAL_UINT: {
label: 'Octal Unsigned Integer',
url: '[[link,settings_types_octal_uint]]',
default_required: true,
},
URL: {
label: 'URL',
url: '[[link,settings_types_url]]'
// Default: empty
},
FILE: {
label: 'File',
url: '[[link,settings_types_file]]'
// Default: empty
},
NAMED_FILTER: {
label: 'Named Filter',
url: '[[link,settings_types_named_filter]]',
no_default: true,
},
NAMED_LIST_FILTER: {
label: 'Named List Filter',
url: '[[link,settings_types_named_list_filter]]'
// Default: empty
},
STRLIST: {
label: 'String List',
url: '[[link,settings_types_strlist]]'
// Default: empty
},
BOOLLIST: {
label: 'Boolean List',
url: '[[link,settings_types_boollist]]'
// Default: empty
},
IN_PORT: {
label: 'Port Number',
url: '[[link,settings_types_in_port]]',
default_required: true,
},
GROUP: {
label: 'Settings Group',
url: '[[link,settings_groups_includes]]'
}
}
158 changes: 3 additions & 155 deletions lib/data/doveadm.data.js
Original file line number Diff line number Diff line change
@@ -1,160 +1,8 @@
import { doveadm_arg_types, doveadm_flag_types, getDoveadmCmdLine } from '../doveadm.js'
import { getVitepressMd } from '../markdown.js'
import { addWatchPaths, loadData, normalizeArrayData } from '../utility.js'
import camelCase from 'camelcase'
import slugify from '@sindresorhus/slugify'

const doveadm_userargs = {
'all-users': {
cli: 'A',
example: false,
type: doveadm_arg_types.BOOL,
text: `Apply operation to all users.`
},
'socket-path': {
cli: 'S',
example: '/var/run/dovecot/doveadm-server',
type: doveadm_arg_types.STRING,
text: `Path to doveadm socket.`
},
user: {
cli: 'u',
example: 'username',
type: doveadm_arg_types.STRING,
text: `UID of user to apply operation to.`,
},
}

const doveadm_userfileargs = {
/* Hidden from documentation.
'trans-flags': {
type: doveadm_arg_types.INTEGER,
text: `Transaction flags.`
},
*/
'user-file': {
cli: 'F',
type: doveadm_arg_types.STRING,
text: `A filename. If set, fetch usernames from file. One username per line.`
},
}

function typeToString(type) {
switch (type) {
case doveadm_arg_types.ARRAY:
return 'array'
case doveadm_arg_types.BOOL:
return 'boolean'
case doveadm_arg_types.INTEGER:
return 'integer'
case doveadm_arg_types.STRING:
return 'string'
case doveadm_arg_types.SEARCH_QUERY:
return 'search_query'
case doveadm_arg_types.ISTREAM:
return 'istream'
}
}

function argToHttpParam(arg) {
return arg.split('-').reduce((s, c) =>
s + (c.charAt(0).toUpperCase() + c.slice(1)))
}

async function normalizeDoveadm(doveadm) {
const md = await getVitepressMd()

for (const [k, v] of Object.entries(doveadm)) {
if (!v) {
delete doveadm[k]
continue
}

if (v.flags && (v.flags & doveadm_flag_types.USER)) {
v.args = { ...v.args, ...doveadm_userargs }
}

if (v.flags && (v.flags & doveadm_flag_types.USERFILE)) {
v.args = { ...v.args, ...doveadm_userfileargs }
}

/* Convert 'man' entry into a markdown link to man page.
* We will add the hash to all URLs for simplicity; for those man
* pages that don't have individual command names, this will just
* be ignored by the browser. */
if (v.man) {
v.man_link = md.renderInline('[[man,' + v.man + ',' + slugify(k) + ']]')
}

/* Change entries. */
for (const k2 of ['added', 'changed', 'deprecated', 'removed']) {
if (v[k2]) {
const changes = []
for (const[k3, v3] of Object.entries(v[k2])) {
changes.push({
text: v3 ? md.render(v3.trim()) : null,
version: md.renderInline('[[' + k2 + ',' + k3 + ']]')
})
}
v[k2] = changes
}
}

/* Response values. */
if (v.response) {
if (v.response.text) {
v.response.text = md.render(String(v.response.text))
}
} else {
delete v['response']
}

/* Text Description. */
if (v.text) {
v.text = md.render(v.text)
}

/* Cmd line arguments. */
v.usage = k + (v.args ? ' ' + getDoveadmCmdLine(v.args) : '')

if (v.args) {
const args = []
for (const [k2, v2] of Object.entries(v.args)) {
if (!v2.hidden) {
args.push({
/* Undefined examples will resolve to undefined. */
cli_only: v2.cli_only,
example: v2.example,
flag: v2.cli ? '-' + v2.cli : (v2.positional ? k2 : '--' + k2),
param: argToHttpParam(k2),
type: typeToString(v2.type),
text: v2.text ? md.render(v2.text) : null
})
}
}
v.args = args
}
if (!v.args || !v.args.length) {
delete v['args']
}

/* HTTP API info. */
v.http_cmd = camelCase(k)
}

return {
doveadm: normalizeArrayData(
doveadm,
['tags']
),
http_api_link: md.renderInline('[[link,doveadm_http_api,HTTP API]]')
}
}
import { addWatchPaths } from '../utility.js'
import { loadDoveadm } from '../doveadm.js'

export default addWatchPaths({
async load() {
return await normalizeDoveadm(
structuredClone(loadData('doveadm').doveadm)
)
return await loadDoveadm()
}
})
18 changes: 3 additions & 15 deletions lib/data/event_categories.data.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { getVitepressMd } from '../markdown.js'
import { addWatchPaths, loadData } from '../utility.js'

async function normalizeEventCategories(categories) {
const md = await getVitepressMd()

for (const [k, v] of Object.entries(categories)) {
v.description = md.renderInline(v.description)
}

return categories
}
import { loadEventCategories } from '../event_categories.js'
import { addWatchPaths } from '../utility.js'

export default addWatchPaths({
async load() {
return await normalizeEventCategories(
structuredClone(loadData('event_categories').categories)
)
return await loadEventCategories()
}
})
18 changes: 3 additions & 15 deletions lib/data/event_reasons.data.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { getVitepressMd } from '../markdown.js'
import { addWatchPaths, loadData } from '../utility.js'

async function normalizeEventReasons(reasons) {
const md = await getVitepressMd()

for (const [k, v] of Object.entries(reasons)) {
v.description = md.renderInline(v.description)
}

return reasons
}
import { addWatchPaths } from '../utility.js'
import { loadEventReasons } from '../event_reasons.js'

export default addWatchPaths({
async load() {
return await normalizeEventReasons(
structuredClone(loadData('event_reasons').reasons)
)
return await loadEventReasons()
}
})
Loading