@axium/server 0.5.3 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.js +1 -1
- package/dist/cli.js +65 -20
- package/dist/config.d.ts +130 -160
- package/dist/config.js +77 -83
- package/dist/database.d.ts +1 -2
- package/dist/database.js +31 -11
- package/dist/io.d.ts +5 -5
- package/dist/io.js +10 -8
- package/dist/plugins.d.ts +51 -0
- package/dist/plugins.js +68 -0
- package/package.json +2 -2
- package/web/auth.ts +2 -2
- package/web/routes/signup/+page.server.ts +1 -1
- package/web/utils.ts +2 -2
package/dist/auth.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Login, Registration } from '@axium/core/schemas';
|
|
|
6
6
|
import { genSaltSync, hashSync } from 'bcryptjs';
|
|
7
7
|
import { randomBytes } from 'node:crypto';
|
|
8
8
|
import { omit } from 'utilium';
|
|
9
|
-
import
|
|
9
|
+
import config from './config.js';
|
|
10
10
|
import * as db from './database.js';
|
|
11
11
|
import { logger } from './io.js';
|
|
12
12
|
export let adapter;
|
package/dist/cli.js
CHANGED
|
@@ -3,9 +3,10 @@ import { Argument, Option, program } from 'commander';
|
|
|
3
3
|
import { styleText } from 'node:util';
|
|
4
4
|
import { getByString, isJSON, setByString } from 'utilium';
|
|
5
5
|
import $pkg from '../package.json' with { type: 'json' };
|
|
6
|
-
import
|
|
6
|
+
import config from './config.js';
|
|
7
7
|
import * as db from './database.js';
|
|
8
8
|
import { _portActions, _portMethods, exit, handleError, output, restrictedPorts } from './io.js';
|
|
9
|
+
import { loadDefaultPlugins, plugins, pluginText, resolvePlugin } from './plugins.js';
|
|
9
10
|
program
|
|
10
11
|
.version($pkg.version)
|
|
11
12
|
.name('axium')
|
|
@@ -16,8 +17,9 @@ program
|
|
|
16
17
|
.option('-c, --config <path>', 'path to the config file');
|
|
17
18
|
program.on('option:debug', () => config.set({ debug: true }));
|
|
18
19
|
program.on('option:config', () => config.load(program.opts().config));
|
|
19
|
-
program.hook('preAction', function (_, action) {
|
|
20
|
+
program.hook('preAction', async function (_, action) {
|
|
20
21
|
config.loadDefaults();
|
|
22
|
+
await loadDefaultPlugins();
|
|
21
23
|
const opt = action.optsWithGlobals();
|
|
22
24
|
opt.force && output.warn('--force: Protections disabled.');
|
|
23
25
|
if (opt.debug === false)
|
|
@@ -32,25 +34,26 @@ const opts = {
|
|
|
32
34
|
config.db.port = port && Number.isSafeInteger(parseInt(port)) ? parseInt(port) : config.db.port;
|
|
33
35
|
}),
|
|
34
36
|
force: new Option('-f, --force', 'force the operation').default(false),
|
|
37
|
+
global: new Option('-g, --global', 'apply the operation globally').default(false),
|
|
35
38
|
};
|
|
36
39
|
const axiumDB = program
|
|
37
40
|
.command('db')
|
|
38
41
|
.alias('database')
|
|
39
|
-
.description('
|
|
42
|
+
.description('Manage the database')
|
|
40
43
|
.option('-t, --timeout <ms>', 'how long to wait for commands to complete.', '1000')
|
|
41
44
|
.addOption(opts.host);
|
|
42
45
|
axiumDB
|
|
43
46
|
.command('init')
|
|
44
|
-
.description('
|
|
47
|
+
.description('Initialize the database')
|
|
45
48
|
.addOption(opts.force)
|
|
46
|
-
.option('-s, --skip', '
|
|
49
|
+
.option('-s, --skip', 'If the user, database, or schema already exists, skip trying to create it.')
|
|
47
50
|
.action(async (opt) => {
|
|
48
51
|
await db.init(opt).catch(handleError);
|
|
49
52
|
});
|
|
50
53
|
axiumDB
|
|
51
54
|
.command('status')
|
|
52
55
|
.alias('stats')
|
|
53
|
-
.description('
|
|
56
|
+
.description('Check the status of the database')
|
|
54
57
|
.action(async () => {
|
|
55
58
|
try {
|
|
56
59
|
console.log(await db.statusText());
|
|
@@ -65,7 +68,7 @@ axiumDB
|
|
|
65
68
|
});
|
|
66
69
|
axiumDB
|
|
67
70
|
.command('drop')
|
|
68
|
-
.description('
|
|
71
|
+
.description('Drop the Axium database and user')
|
|
69
72
|
.addOption(opts.force)
|
|
70
73
|
.action(async (opt) => {
|
|
71
74
|
const stats = await db.status().catch(exit);
|
|
@@ -81,7 +84,7 @@ axiumDB
|
|
|
81
84
|
});
|
|
82
85
|
axiumDB
|
|
83
86
|
.command('wipe')
|
|
84
|
-
.description('
|
|
87
|
+
.description('Wipe the database')
|
|
85
88
|
.addOption(opts.force)
|
|
86
89
|
.action(async (opt) => {
|
|
87
90
|
const stats = await db.status().catch(exit);
|
|
@@ -95,21 +98,17 @@ axiumDB
|
|
|
95
98
|
await db.wipe(opt).catch(exit);
|
|
96
99
|
await db.database.destroy();
|
|
97
100
|
});
|
|
98
|
-
const axiumConfig = program
|
|
99
|
-
.command('config')
|
|
100
|
-
.description('manage the configuration')
|
|
101
|
-
.option('-j, --json', 'values are JSON encoded')
|
|
102
|
-
.option('-g, --global', 'apply to the global config');
|
|
101
|
+
const axiumConfig = program.command('config').description('Manage the configuration').addOption(opts.global).option('-j, --json', 'values are JSON encoded');
|
|
103
102
|
axiumConfig
|
|
104
103
|
.command('dump')
|
|
105
104
|
.description('Output the entire current configuration')
|
|
106
105
|
.action(() => {
|
|
107
|
-
const value = config
|
|
106
|
+
const value = config;
|
|
108
107
|
console.log(axiumConfig.optsWithGlobals().json ? JSON.stringify(value) : value);
|
|
109
108
|
});
|
|
110
109
|
axiumConfig
|
|
111
110
|
.command('get')
|
|
112
|
-
.description('
|
|
111
|
+
.description('Get a config value')
|
|
113
112
|
.argument('<key>', 'the key to get')
|
|
114
113
|
.action((key) => {
|
|
115
114
|
const value = getByString(config, key);
|
|
@@ -137,16 +136,53 @@ axiumConfig
|
|
|
137
136
|
for (const path of config.files.keys())
|
|
138
137
|
console.log(path);
|
|
139
138
|
});
|
|
139
|
+
const axiumPlugin = program
|
|
140
|
+
.command('plugins')
|
|
141
|
+
.description('Manage plugins')
|
|
142
|
+
.addOption(opts.global)
|
|
143
|
+
.option('--safe', 'do not perform actions that would execute code from plugins.');
|
|
144
|
+
axiumPlugin
|
|
145
|
+
.command('list')
|
|
146
|
+
.alias('ls')
|
|
147
|
+
.description('List loaded plugins')
|
|
148
|
+
.option('-l, --long', 'use the long listing format')
|
|
149
|
+
.option('--no-versions', 'do not show plugin versions')
|
|
150
|
+
.action((opt) => {
|
|
151
|
+
if (!plugins.size) {
|
|
152
|
+
console.log('No plugins loaded.');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!opt.long) {
|
|
156
|
+
console.log(Array.from(plugins)
|
|
157
|
+
.map(plugin => plugin.name)
|
|
158
|
+
.join(', '));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
console.log(styleText('whiteBright', plugins.size + ' plugin(s) loaded:'));
|
|
162
|
+
for (const plugin of plugins) {
|
|
163
|
+
console.log(plugin.name, styleText('dim', `(${plugin.id})`), opt.versions ? plugin.version : '');
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
axiumPlugin
|
|
167
|
+
.command('info')
|
|
168
|
+
.description('Get information about a plugin')
|
|
169
|
+
.argument('<plugin>', 'the plugin to get information about')
|
|
170
|
+
.action((search) => {
|
|
171
|
+
const plugin = resolvePlugin(search);
|
|
172
|
+
if (!plugin)
|
|
173
|
+
exit(`Can't find a plugin matching "${search}"`);
|
|
174
|
+
console.log(pluginText(plugin));
|
|
175
|
+
});
|
|
140
176
|
program
|
|
141
177
|
.command('status')
|
|
142
178
|
.alias('stats')
|
|
143
|
-
.description('
|
|
179
|
+
.description('Get information about the server')
|
|
144
180
|
.addOption(opts.host)
|
|
145
181
|
.action(async () => {
|
|
146
182
|
console.log('Axium Server v' + program.version());
|
|
147
|
-
console.log('Debug mode:', config.debug ? styleText('yellow', 'enabled') : 'disabled');
|
|
148
|
-
console.log('Loaded config files:', config.files.keys().toArray().join(', '));
|
|
149
|
-
process.stdout.write('Database: ');
|
|
183
|
+
console.log(styleText('whiteBright', 'Debug mode:'), config.debug ? styleText('yellow', 'enabled') : 'disabled');
|
|
184
|
+
console.log(styleText('whiteBright', 'Loaded config files:'), config.files.keys().toArray().join(', '));
|
|
185
|
+
process.stdout.write(styleText('whiteBright', 'Database: '));
|
|
150
186
|
try {
|
|
151
187
|
console.log(await db.statusText());
|
|
152
188
|
}
|
|
@@ -154,7 +190,16 @@ program
|
|
|
154
190
|
output.error('Unavailable');
|
|
155
191
|
}
|
|
156
192
|
await db.database.destroy();
|
|
157
|
-
console.log('Credentials authentication:', config.auth.credentials ? styleText('yellow', 'enabled') : 'disabled');
|
|
193
|
+
console.log(styleText('whiteBright', 'Credentials authentication:'), config.auth.credentials ? styleText('yellow', 'enabled') : 'disabled');
|
|
194
|
+
console.log(styleText('whiteBright', 'Loaded plugins:'), Array.from(plugins)
|
|
195
|
+
.map(plugin => plugin.id)
|
|
196
|
+
.join(', ') || styleText('dim', '(none)'));
|
|
197
|
+
for (const plugin of plugins) {
|
|
198
|
+
if (!plugin.statusText)
|
|
199
|
+
continue;
|
|
200
|
+
console.log(styleText('bold', plugin.name + ':'));
|
|
201
|
+
console.log(plugin.statusText());
|
|
202
|
+
}
|
|
158
203
|
});
|
|
159
204
|
program
|
|
160
205
|
.command('ports')
|
package/dist/config.d.ts
CHANGED
|
@@ -1,170 +1,144 @@
|
|
|
1
1
|
import { type PartialRecursive } from 'utilium';
|
|
2
2
|
import * as z from 'zod';
|
|
3
|
-
export declare const
|
|
4
|
-
host: z.ZodString;
|
|
5
|
-
port: z.ZodNumber;
|
|
6
|
-
password: z.ZodString;
|
|
7
|
-
user: z.ZodString;
|
|
8
|
-
database: z.ZodString;
|
|
9
|
-
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
host: string;
|
|
11
|
-
port: number;
|
|
12
|
-
password: string;
|
|
13
|
-
user: string;
|
|
14
|
-
database: string;
|
|
15
|
-
}, {
|
|
16
|
-
host: string;
|
|
17
|
-
port: number;
|
|
18
|
-
password: string;
|
|
19
|
-
user: string;
|
|
20
|
-
database: string;
|
|
21
|
-
}>;
|
|
22
|
-
export type Database = z.infer<typeof Database>;
|
|
23
|
-
export declare const db: Database;
|
|
24
|
-
export declare const Auth: z.ZodObject<{
|
|
25
|
-
credentials: z.ZodBoolean;
|
|
26
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
-
secret: z.ZodString;
|
|
28
|
-
secure_cookies: z.ZodBoolean;
|
|
29
|
-
}, "strip", z.ZodTypeAny, {
|
|
30
|
-
credentials: boolean;
|
|
31
|
-
secret: string;
|
|
32
|
-
secure_cookies: boolean;
|
|
33
|
-
debug?: boolean | undefined;
|
|
34
|
-
}, {
|
|
35
|
-
credentials: boolean;
|
|
36
|
-
secret: string;
|
|
37
|
-
secure_cookies: boolean;
|
|
38
|
-
debug?: boolean | undefined;
|
|
39
|
-
}>;
|
|
40
|
-
export type Auth = z.infer<typeof Auth>;
|
|
41
|
-
export declare const auth: Auth;
|
|
42
|
-
export declare const Log: z.ZodObject<{
|
|
43
|
-
level: z.ZodEnum<["error", "warn", "notice", "info", "debug"]>;
|
|
44
|
-
console: z.ZodBoolean;
|
|
45
|
-
}, "strip", z.ZodTypeAny, {
|
|
46
|
-
level: "warn" | "error" | "debug" | "notice" | "info";
|
|
47
|
-
console: boolean;
|
|
48
|
-
}, {
|
|
49
|
-
level: "warn" | "error" | "debug" | "notice" | "info";
|
|
50
|
-
console: boolean;
|
|
51
|
-
}>;
|
|
52
|
-
export type Log = z.infer<typeof Log>;
|
|
53
|
-
export declare const log: Log;
|
|
54
|
-
export declare const Web: z.ZodObject<{
|
|
55
|
-
prefix: z.ZodString;
|
|
56
|
-
}, "strip", z.ZodTypeAny, {
|
|
57
|
-
prefix: string;
|
|
58
|
-
}, {
|
|
59
|
-
prefix: string;
|
|
60
|
-
}>;
|
|
61
|
-
export type Web = z.infer<typeof Web>;
|
|
62
|
-
export declare const web: Web;
|
|
63
|
-
export declare const Config: z.ZodObject<{
|
|
3
|
+
export declare const Schema: z.ZodObject<{
|
|
64
4
|
auth: z.ZodObject<{
|
|
65
|
-
credentials: z.
|
|
66
|
-
debug: z.
|
|
67
|
-
secret: z.
|
|
68
|
-
secure_cookies: z.
|
|
5
|
+
credentials: z.ZodBoolean;
|
|
6
|
+
debug: z.ZodBoolean;
|
|
7
|
+
secret: z.ZodString;
|
|
8
|
+
secure_cookies: z.ZodBoolean;
|
|
69
9
|
}, "strip", z.ZodTypeAny, {
|
|
70
|
-
debug
|
|
71
|
-
credentials
|
|
72
|
-
secret
|
|
73
|
-
secure_cookies
|
|
10
|
+
debug: boolean;
|
|
11
|
+
credentials: boolean;
|
|
12
|
+
secret: string;
|
|
13
|
+
secure_cookies: boolean;
|
|
74
14
|
}, {
|
|
75
|
-
debug
|
|
76
|
-
credentials
|
|
77
|
-
secret
|
|
78
|
-
secure_cookies
|
|
15
|
+
debug: boolean;
|
|
16
|
+
credentials: boolean;
|
|
17
|
+
secret: string;
|
|
18
|
+
secure_cookies: boolean;
|
|
79
19
|
}>;
|
|
80
|
-
debug: z.ZodBoolean;
|
|
81
20
|
db: z.ZodObject<{
|
|
82
|
-
host: z.
|
|
83
|
-
port: z.
|
|
84
|
-
password: z.
|
|
85
|
-
user: z.
|
|
86
|
-
database: z.
|
|
21
|
+
host: z.ZodString;
|
|
22
|
+
port: z.ZodNumber;
|
|
23
|
+
password: z.ZodString;
|
|
24
|
+
user: z.ZodString;
|
|
25
|
+
database: z.ZodString;
|
|
87
26
|
}, "strip", z.ZodTypeAny, {
|
|
88
|
-
host
|
|
89
|
-
port
|
|
90
|
-
password
|
|
91
|
-
user
|
|
92
|
-
database
|
|
27
|
+
host: string;
|
|
28
|
+
port: number;
|
|
29
|
+
password: string;
|
|
30
|
+
user: string;
|
|
31
|
+
database: string;
|
|
93
32
|
}, {
|
|
94
|
-
host
|
|
95
|
-
port
|
|
96
|
-
password
|
|
97
|
-
user
|
|
98
|
-
database
|
|
33
|
+
host: string;
|
|
34
|
+
port: number;
|
|
35
|
+
password: string;
|
|
36
|
+
user: string;
|
|
37
|
+
database: string;
|
|
99
38
|
}>;
|
|
39
|
+
debug: z.ZodBoolean;
|
|
100
40
|
log: z.ZodObject<{
|
|
101
|
-
level: z.
|
|
102
|
-
console: z.
|
|
41
|
+
level: z.ZodEnum<["error", "warn", "notice", "info", "debug"]>;
|
|
42
|
+
console: z.ZodBoolean;
|
|
103
43
|
}, "strip", z.ZodTypeAny, {
|
|
104
|
-
level
|
|
105
|
-
console
|
|
44
|
+
level: "debug" | "info" | "warn" | "error" | "notice";
|
|
45
|
+
console: boolean;
|
|
106
46
|
}, {
|
|
107
|
-
level
|
|
108
|
-
console
|
|
47
|
+
level: "debug" | "info" | "warn" | "error" | "notice";
|
|
48
|
+
console: boolean;
|
|
109
49
|
}>;
|
|
110
50
|
web: z.ZodObject<{
|
|
111
|
-
prefix: z.
|
|
51
|
+
prefix: z.ZodString;
|
|
112
52
|
}, "strip", z.ZodTypeAny, {
|
|
113
|
-
prefix
|
|
53
|
+
prefix: string;
|
|
114
54
|
}, {
|
|
115
|
-
prefix
|
|
55
|
+
prefix: string;
|
|
116
56
|
}>;
|
|
117
57
|
}, "strip", z.ZodTypeAny, {
|
|
118
|
-
log: {
|
|
119
|
-
level?: "warn" | "error" | "debug" | "notice" | "info" | undefined;
|
|
120
|
-
console?: boolean | undefined;
|
|
121
|
-
};
|
|
122
58
|
debug: boolean;
|
|
123
59
|
auth: {
|
|
124
|
-
debug
|
|
125
|
-
credentials
|
|
126
|
-
secret
|
|
127
|
-
secure_cookies
|
|
60
|
+
debug: boolean;
|
|
61
|
+
credentials: boolean;
|
|
62
|
+
secret: string;
|
|
63
|
+
secure_cookies: boolean;
|
|
128
64
|
};
|
|
129
65
|
db: {
|
|
130
|
-
host
|
|
131
|
-
port
|
|
132
|
-
password
|
|
133
|
-
user
|
|
134
|
-
database
|
|
66
|
+
host: string;
|
|
67
|
+
port: number;
|
|
68
|
+
password: string;
|
|
69
|
+
user: string;
|
|
70
|
+
database: string;
|
|
71
|
+
};
|
|
72
|
+
log: {
|
|
73
|
+
level: "debug" | "info" | "warn" | "error" | "notice";
|
|
74
|
+
console: boolean;
|
|
135
75
|
};
|
|
136
76
|
web: {
|
|
137
|
-
prefix
|
|
77
|
+
prefix: string;
|
|
138
78
|
};
|
|
139
79
|
}, {
|
|
140
|
-
log: {
|
|
141
|
-
level?: "warn" | "error" | "debug" | "notice" | "info" | undefined;
|
|
142
|
-
console?: boolean | undefined;
|
|
143
|
-
};
|
|
144
80
|
debug: boolean;
|
|
145
81
|
auth: {
|
|
146
|
-
debug
|
|
147
|
-
credentials
|
|
148
|
-
secret
|
|
149
|
-
secure_cookies
|
|
82
|
+
debug: boolean;
|
|
83
|
+
credentials: boolean;
|
|
84
|
+
secret: string;
|
|
85
|
+
secure_cookies: boolean;
|
|
150
86
|
};
|
|
151
87
|
db: {
|
|
152
|
-
host
|
|
153
|
-
port
|
|
154
|
-
password
|
|
155
|
-
user
|
|
156
|
-
database
|
|
88
|
+
host: string;
|
|
89
|
+
port: number;
|
|
90
|
+
password: string;
|
|
91
|
+
user: string;
|
|
92
|
+
database: string;
|
|
93
|
+
};
|
|
94
|
+
log: {
|
|
95
|
+
level: "debug" | "info" | "warn" | "error" | "notice";
|
|
96
|
+
console: boolean;
|
|
157
97
|
};
|
|
158
98
|
web: {
|
|
159
|
-
prefix
|
|
99
|
+
prefix: string;
|
|
160
100
|
};
|
|
161
101
|
}>;
|
|
102
|
+
export interface Config extends Record<string, unknown>, z.infer<typeof Schema> {
|
|
103
|
+
}
|
|
104
|
+
export declare const configFiles: Map<string, PartialRecursive<Config>>;
|
|
105
|
+
export declare const config: {
|
|
106
|
+
auth: {
|
|
107
|
+
credentials: false;
|
|
108
|
+
debug: false;
|
|
109
|
+
secret: string;
|
|
110
|
+
secure_cookies: true;
|
|
111
|
+
};
|
|
112
|
+
db: {
|
|
113
|
+
database: string;
|
|
114
|
+
host: string;
|
|
115
|
+
password: string;
|
|
116
|
+
port: number;
|
|
117
|
+
user: string;
|
|
118
|
+
};
|
|
119
|
+
debug: false;
|
|
120
|
+
log: {
|
|
121
|
+
console: true;
|
|
122
|
+
level: "info";
|
|
123
|
+
};
|
|
124
|
+
web: {
|
|
125
|
+
prefix: string;
|
|
126
|
+
};
|
|
127
|
+
findPath: typeof findConfigPath;
|
|
128
|
+
load: typeof loadConfig;
|
|
129
|
+
loadDefaults: typeof loadDefaultConfigs;
|
|
130
|
+
save: typeof saveConfig;
|
|
131
|
+
saveTo: typeof saveConfigTo;
|
|
132
|
+
set: typeof setConfig;
|
|
133
|
+
files: Map<string, PartialRecursive<Config>>;
|
|
134
|
+
};
|
|
135
|
+
export default config;
|
|
162
136
|
export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
163
137
|
auth: z.ZodOptional<z.ZodObject<{
|
|
164
|
-
credentials: z.ZodOptional<z.
|
|
165
|
-
debug: z.ZodOptional<z.
|
|
166
|
-
secret: z.ZodOptional<z.
|
|
167
|
-
secure_cookies: z.ZodOptional<z.
|
|
138
|
+
credentials: z.ZodOptional<z.ZodBoolean>;
|
|
139
|
+
debug: z.ZodOptional<z.ZodBoolean>;
|
|
140
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
141
|
+
secure_cookies: z.ZodOptional<z.ZodBoolean>;
|
|
168
142
|
}, "strip", z.ZodTypeAny, {
|
|
169
143
|
debug?: boolean | undefined;
|
|
170
144
|
credentials?: boolean | undefined;
|
|
@@ -176,13 +150,12 @@ export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
|
176
150
|
secret?: string | undefined;
|
|
177
151
|
secure_cookies?: boolean | undefined;
|
|
178
152
|
}>>;
|
|
179
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
180
153
|
db: z.ZodOptional<z.ZodObject<{
|
|
181
|
-
host: z.ZodOptional<z.
|
|
182
|
-
port: z.ZodOptional<z.
|
|
183
|
-
password: z.ZodOptional<z.
|
|
184
|
-
user: z.ZodOptional<z.
|
|
185
|
-
database: z.ZodOptional<z.
|
|
154
|
+
host: z.ZodOptional<z.ZodString>;
|
|
155
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
156
|
+
password: z.ZodOptional<z.ZodString>;
|
|
157
|
+
user: z.ZodOptional<z.ZodString>;
|
|
158
|
+
database: z.ZodOptional<z.ZodString>;
|
|
186
159
|
}, "strip", z.ZodTypeAny, {
|
|
187
160
|
host?: string | undefined;
|
|
188
161
|
port?: number | undefined;
|
|
@@ -196,18 +169,19 @@ export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
|
196
169
|
user?: string | undefined;
|
|
197
170
|
database?: string | undefined;
|
|
198
171
|
}>>;
|
|
172
|
+
debug: z.ZodOptional<z.ZodBoolean>;
|
|
199
173
|
log: z.ZodOptional<z.ZodObject<{
|
|
200
|
-
level: z.ZodOptional<z.
|
|
201
|
-
console: z.ZodOptional<z.
|
|
174
|
+
level: z.ZodOptional<z.ZodEnum<["error", "warn", "notice", "info", "debug"]>>;
|
|
175
|
+
console: z.ZodOptional<z.ZodBoolean>;
|
|
202
176
|
}, "strip", z.ZodTypeAny, {
|
|
203
|
-
level?: "
|
|
177
|
+
level?: "debug" | "info" | "warn" | "error" | "notice" | undefined;
|
|
204
178
|
console?: boolean | undefined;
|
|
205
179
|
}, {
|
|
206
|
-
level?: "
|
|
180
|
+
level?: "debug" | "info" | "warn" | "error" | "notice" | undefined;
|
|
207
181
|
console?: boolean | undefined;
|
|
208
182
|
}>>;
|
|
209
183
|
web: z.ZodOptional<z.ZodObject<{
|
|
210
|
-
prefix: z.ZodOptional<z.
|
|
184
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
211
185
|
}, "strip", z.ZodTypeAny, {
|
|
212
186
|
prefix?: string | undefined;
|
|
213
187
|
}, {
|
|
@@ -216,10 +190,6 @@ export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
|
216
190
|
}, {
|
|
217
191
|
include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
218
192
|
}>, "strip", z.ZodTypeAny, {
|
|
219
|
-
log?: {
|
|
220
|
-
level?: "warn" | "error" | "debug" | "notice" | "info" | undefined;
|
|
221
|
-
console?: boolean | undefined;
|
|
222
|
-
} | undefined;
|
|
223
193
|
debug?: boolean | undefined;
|
|
224
194
|
auth?: {
|
|
225
195
|
debug?: boolean | undefined;
|
|
@@ -234,15 +204,15 @@ export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
|
234
204
|
user?: string | undefined;
|
|
235
205
|
database?: string | undefined;
|
|
236
206
|
} | undefined;
|
|
207
|
+
log?: {
|
|
208
|
+
level?: "debug" | "info" | "warn" | "error" | "notice" | undefined;
|
|
209
|
+
console?: boolean | undefined;
|
|
210
|
+
} | undefined;
|
|
237
211
|
web?: {
|
|
238
212
|
prefix?: string | undefined;
|
|
239
213
|
} | undefined;
|
|
240
214
|
include?: string[] | undefined;
|
|
241
215
|
}, {
|
|
242
|
-
log?: {
|
|
243
|
-
level?: "warn" | "error" | "debug" | "notice" | "info" | undefined;
|
|
244
|
-
console?: boolean | undefined;
|
|
245
|
-
} | undefined;
|
|
246
216
|
debug?: boolean | undefined;
|
|
247
217
|
auth?: {
|
|
248
218
|
debug?: boolean | undefined;
|
|
@@ -257,21 +227,21 @@ export declare const File: z.ZodObject<z.objectUtil.extendShape<{
|
|
|
257
227
|
user?: string | undefined;
|
|
258
228
|
database?: string | undefined;
|
|
259
229
|
} | undefined;
|
|
230
|
+
log?: {
|
|
231
|
+
level?: "debug" | "info" | "warn" | "error" | "notice" | undefined;
|
|
232
|
+
console?: boolean | undefined;
|
|
233
|
+
} | undefined;
|
|
260
234
|
web?: {
|
|
261
235
|
prefix?: string | undefined;
|
|
262
236
|
} | undefined;
|
|
263
237
|
include?: string[] | undefined;
|
|
264
238
|
}>;
|
|
265
|
-
export
|
|
266
|
-
export interface Config extends z.infer<typeof Config> {
|
|
239
|
+
export interface File extends PartialRecursive<Config>, z.infer<typeof File> {
|
|
267
240
|
}
|
|
268
|
-
export declare let debug: boolean;
|
|
269
|
-
export declare function get(): Config;
|
|
270
241
|
/**
|
|
271
242
|
* Update the current config
|
|
272
243
|
*/
|
|
273
|
-
export declare function
|
|
274
|
-
export declare const files: Map<string, PartialRecursive<Config>>;
|
|
244
|
+
export declare function setConfig(other: PartialRecursive<Config>): void;
|
|
275
245
|
export interface LoadOptions {
|
|
276
246
|
/**
|
|
277
247
|
* If enabled, the config file will be not be loaded if it does not match the schema.
|
|
@@ -289,17 +259,17 @@ export interface LoadOptions {
|
|
|
289
259
|
/**
|
|
290
260
|
* Load the config from the provided path
|
|
291
261
|
*/
|
|
292
|
-
export declare function
|
|
293
|
-
export declare function
|
|
262
|
+
export declare function loadConfig(path: string, options?: LoadOptions): void;
|
|
263
|
+
export declare function loadDefaultConfigs(): void;
|
|
294
264
|
/**
|
|
295
265
|
* Update the current config and write the updated config to the appropriate file
|
|
296
266
|
*/
|
|
297
|
-
export declare function
|
|
267
|
+
export declare function saveConfig(changed: PartialRecursive<Config>, global?: boolean): void;
|
|
298
268
|
/**
|
|
299
269
|
* Update the current config and write the updated config to the provided path
|
|
300
270
|
*/
|
|
301
|
-
export declare function
|
|
271
|
+
export declare function saveConfigTo(path: string, changed: PartialRecursive<Config>): void;
|
|
302
272
|
/**
|
|
303
273
|
* Find the path to the config file
|
|
304
274
|
*/
|
|
305
|
-
export declare function
|
|
275
|
+
export declare function findConfigPath(global: boolean): string;
|
package/dist/config.js
CHANGED
|
@@ -2,87 +2,81 @@
|
|
|
2
2
|
import { levelText } from 'logzen';
|
|
3
3
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { dirname, join } from 'node:path/posix';
|
|
5
|
-
import {
|
|
5
|
+
import { deepAssign } from 'utilium';
|
|
6
6
|
import * as z from 'zod';
|
|
7
7
|
import { findDir, logger, output } from './io.js';
|
|
8
|
-
export const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
export const Auth = z.object({
|
|
23
|
-
credentials: z.boolean(),
|
|
24
|
-
debug: z.boolean().optional(),
|
|
25
|
-
secret: z.string(),
|
|
26
|
-
secure_cookies: z.boolean(),
|
|
27
|
-
});
|
|
28
|
-
export const auth = {
|
|
29
|
-
credentials: false,
|
|
30
|
-
secret: '',
|
|
31
|
-
secure_cookies: false,
|
|
32
|
-
};
|
|
33
|
-
export const Log = z.object({
|
|
34
|
-
level: z.enum(levelText),
|
|
35
|
-
console: z.boolean(),
|
|
36
|
-
});
|
|
37
|
-
export const log = {
|
|
38
|
-
level: 'info',
|
|
39
|
-
console: true,
|
|
40
|
-
};
|
|
41
|
-
export const Web = z.object({
|
|
42
|
-
prefix: z.string(),
|
|
43
|
-
});
|
|
44
|
-
export const web = {
|
|
45
|
-
prefix: '',
|
|
46
|
-
};
|
|
47
|
-
export const Config = z.object({
|
|
48
|
-
auth: Auth.partial(),
|
|
8
|
+
export const Schema = z.object({
|
|
9
|
+
auth: z.object({
|
|
10
|
+
credentials: z.boolean(),
|
|
11
|
+
debug: z.boolean(),
|
|
12
|
+
secret: z.string(),
|
|
13
|
+
secure_cookies: z.boolean(),
|
|
14
|
+
}),
|
|
15
|
+
db: z.object({
|
|
16
|
+
host: z.string(),
|
|
17
|
+
port: z.number(),
|
|
18
|
+
password: z.string(),
|
|
19
|
+
user: z.string(),
|
|
20
|
+
database: z.string(),
|
|
21
|
+
}),
|
|
49
22
|
debug: z.boolean(),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
23
|
+
log: z.object({
|
|
24
|
+
level: z.enum(levelText),
|
|
25
|
+
console: z.boolean(),
|
|
26
|
+
}),
|
|
27
|
+
web: z.object({
|
|
28
|
+
prefix: z.string(),
|
|
29
|
+
}),
|
|
53
30
|
});
|
|
31
|
+
export const configFiles = new Map();
|
|
32
|
+
export const config = {
|
|
33
|
+
auth: {
|
|
34
|
+
credentials: false,
|
|
35
|
+
debug: false,
|
|
36
|
+
secret: '',
|
|
37
|
+
secure_cookies: true,
|
|
38
|
+
},
|
|
39
|
+
db: {
|
|
40
|
+
database: process.env.PGDATABASE || 'axium',
|
|
41
|
+
host: process.env.PGHOST || 'localhost',
|
|
42
|
+
password: process.env.PGPASSWORD || '',
|
|
43
|
+
port: process.env.PGPORT && Number.isSafeInteger(parseInt(process.env.PGPORT)) ? parseInt(process.env.PGPORT) : 5432,
|
|
44
|
+
user: process.env.PGUSER || 'axium',
|
|
45
|
+
},
|
|
46
|
+
debug: false,
|
|
47
|
+
log: {
|
|
48
|
+
console: true,
|
|
49
|
+
level: 'info',
|
|
50
|
+
},
|
|
51
|
+
web: {
|
|
52
|
+
prefix: '',
|
|
53
|
+
},
|
|
54
|
+
findPath: findConfigPath,
|
|
55
|
+
load: loadConfig,
|
|
56
|
+
loadDefaults: loadDefaultConfigs,
|
|
57
|
+
save: saveConfig,
|
|
58
|
+
saveTo: saveConfigTo,
|
|
59
|
+
set: setConfig,
|
|
60
|
+
files: configFiles,
|
|
61
|
+
};
|
|
62
|
+
export default config;
|
|
54
63
|
// config from file
|
|
55
|
-
export const File =
|
|
64
|
+
export const File = Schema.deepPartial().extend({
|
|
56
65
|
include: z.array(z.string()).optional(),
|
|
57
66
|
});
|
|
58
|
-
export let debug = false;
|
|
59
|
-
export function get() {
|
|
60
|
-
return {
|
|
61
|
-
auth,
|
|
62
|
-
db,
|
|
63
|
-
debug,
|
|
64
|
-
log,
|
|
65
|
-
web,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
67
|
/**
|
|
69
68
|
* Update the current config
|
|
70
69
|
*/
|
|
71
|
-
export function
|
|
72
|
-
|
|
73
|
-
debug = config.debug ?? debug;
|
|
74
|
-
assignWithDefaults(db, config.db ?? {});
|
|
75
|
-
assignWithDefaults(log, config.log ?? {});
|
|
76
|
-
assignWithDefaults(web, config.web ?? {});
|
|
70
|
+
export function setConfig(other) {
|
|
71
|
+
deepAssign(config, other);
|
|
77
72
|
logger.detach(output);
|
|
78
|
-
if (log.console)
|
|
79
|
-
logger.attach(output, { output: log.level });
|
|
73
|
+
if (config.log.console)
|
|
74
|
+
logger.attach(output, { output: config.log.level });
|
|
80
75
|
}
|
|
81
|
-
export const files = new Map();
|
|
82
76
|
/**
|
|
83
77
|
* Load the config from the provided path
|
|
84
78
|
*/
|
|
85
|
-
export function
|
|
79
|
+
export function loadConfig(path, options = {}) {
|
|
86
80
|
let json;
|
|
87
81
|
try {
|
|
88
82
|
json = JSON.parse(readFileSync(path, 'utf8'));
|
|
@@ -90,42 +84,42 @@ export function load(path, options = {}) {
|
|
|
90
84
|
catch (e) {
|
|
91
85
|
if (!options.optional)
|
|
92
86
|
throw e;
|
|
93
|
-
debug && output.debug(`Skipping config at ${path} (${e.message})`);
|
|
87
|
+
config.debug && output.debug(`Skipping config at ${path} (${e.message})`);
|
|
94
88
|
return;
|
|
95
89
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
for (const include of
|
|
100
|
-
|
|
90
|
+
const file = options.strict ? File.parse(json) : json;
|
|
91
|
+
configFiles.set(path, file);
|
|
92
|
+
setConfig(file);
|
|
93
|
+
for (const include of file.include ?? [])
|
|
94
|
+
loadConfig(join(dirname(path), include), { optional: true });
|
|
101
95
|
}
|
|
102
|
-
export function
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
export function loadDefaultConfigs() {
|
|
97
|
+
loadConfig(findConfigPath(true), { optional: true });
|
|
98
|
+
loadConfig(findConfigPath(false), { optional: true });
|
|
105
99
|
}
|
|
106
100
|
/**
|
|
107
101
|
* Update the current config and write the updated config to the appropriate file
|
|
108
102
|
*/
|
|
109
|
-
export function
|
|
110
|
-
|
|
103
|
+
export function saveConfig(changed, global = false) {
|
|
104
|
+
saveConfigTo(process.env.AXIUM_CONFIG ?? findConfigPath(global), changed);
|
|
111
105
|
}
|
|
112
106
|
/**
|
|
113
107
|
* Update the current config and write the updated config to the provided path
|
|
114
108
|
*/
|
|
115
|
-
export function
|
|
116
|
-
|
|
117
|
-
const config =
|
|
109
|
+
export function saveConfigTo(path, changed) {
|
|
110
|
+
setConfig(changed);
|
|
111
|
+
const config = configFiles.get(path) ?? {};
|
|
118
112
|
Object.assign(config, { ...changed, db: { ...config.db, ...changed.db } });
|
|
119
|
-
debug && output.debug(`Wrote config to ${path}`);
|
|
113
|
+
config.debug && output.debug(`Wrote config to ${path}`);
|
|
120
114
|
writeFileSync(path, JSON.stringify(config));
|
|
121
115
|
}
|
|
122
116
|
/**
|
|
123
117
|
* Find the path to the config file
|
|
124
118
|
*/
|
|
125
|
-
export function
|
|
119
|
+
export function findConfigPath(global) {
|
|
126
120
|
if (process.env.AXIUM_CONFIG)
|
|
127
121
|
return process.env.AXIUM_CONFIG;
|
|
128
122
|
return join(findDir(global), 'config.json');
|
|
129
123
|
}
|
|
130
124
|
if (process.env.AXIUM_CONFIG)
|
|
131
|
-
|
|
125
|
+
loadConfig(process.env.AXIUM_CONFIG);
|
package/dist/database.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { AdapterAccountType as db } from '@auth/core/adapters';
|
|
2
2
|
import { Kysely, type GeneratedAlways } from 'kysely';
|
|
3
3
|
import type { Preferences } from './auth.js';
|
|
4
|
-
import * as config from './config.js';
|
|
5
4
|
import { type MaybeOutput, type WithOutput } from './io.js';
|
|
6
5
|
export interface Schema {
|
|
7
6
|
User: {
|
|
@@ -67,7 +66,7 @@ export interface InitOptions extends OpOptions {
|
|
|
67
66
|
skip: boolean;
|
|
68
67
|
}
|
|
69
68
|
export declare function shouldRecreate(opt: InitOptions & WithOutput): boolean;
|
|
70
|
-
export declare function init(opt: InitOptions): Promise<
|
|
69
|
+
export declare function init(opt: InitOptions): Promise<void>;
|
|
71
70
|
/**
|
|
72
71
|
* Completely remove Axium from the database.
|
|
73
72
|
*/
|
package/dist/database.js
CHANGED
|
@@ -53,8 +53,9 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
53
53
|
import { Kysely, PostgresDialect, sql } from 'kysely';
|
|
54
54
|
import { randomBytes } from 'node:crypto';
|
|
55
55
|
import pg from 'pg';
|
|
56
|
-
import
|
|
56
|
+
import config from './config.js';
|
|
57
57
|
import { _fixOutput, run, someWarnings } from './io.js';
|
|
58
|
+
import { plugins } from './plugins.js';
|
|
58
59
|
export let database;
|
|
59
60
|
export function connect() {
|
|
60
61
|
if (database)
|
|
@@ -107,7 +108,7 @@ export async function init(opt) {
|
|
|
107
108
|
opt.output('debug', 'Generated password and wrote to global config');
|
|
108
109
|
}
|
|
109
110
|
const _sql = (command, message) => run(opt, message, `sudo -u postgres psql -c "${command}"`);
|
|
110
|
-
const
|
|
111
|
+
const warnExists = someWarnings(opt.output, [/(schema|relation) "\w+" already exists/, 'already exists.']);
|
|
111
112
|
const done = () => opt.output('done');
|
|
112
113
|
await _sql('CREATE DATABASE axium', 'Creating database').catch(async (error) => {
|
|
113
114
|
if (error != 'database "axium" already exists')
|
|
@@ -145,7 +146,7 @@ export async function init(opt) {
|
|
|
145
146
|
.addColumn('preferences', 'jsonb', col => col.notNull().defaultTo(sql `'{}'::jsonb`))
|
|
146
147
|
.execute()
|
|
147
148
|
.then(done)
|
|
148
|
-
.catch(
|
|
149
|
+
.catch(warnExists);
|
|
149
150
|
opt.output('start', 'Creating table Account');
|
|
150
151
|
await db.schema
|
|
151
152
|
.createTable('Account')
|
|
@@ -163,9 +164,9 @@ export async function init(opt) {
|
|
|
163
164
|
.addColumn('session_state', 'text')
|
|
164
165
|
.execute()
|
|
165
166
|
.then(done)
|
|
166
|
-
.catch(
|
|
167
|
+
.catch(warnExists);
|
|
167
168
|
opt.output('start', 'Creating index for Account.userId');
|
|
168
|
-
await db.schema.createIndex('Account_userId_index').on('Account').column('userId').execute().then(done).catch(
|
|
169
|
+
await db.schema.createIndex('Account_userId_index').on('Account').column('userId').execute().then(done).catch(warnExists);
|
|
169
170
|
opt.output('start', 'Creating table Session');
|
|
170
171
|
await db.schema
|
|
171
172
|
.createTable('Session')
|
|
@@ -175,9 +176,9 @@ export async function init(opt) {
|
|
|
175
176
|
.addColumn('expires', 'timestamptz', col => col.notNull())
|
|
176
177
|
.execute()
|
|
177
178
|
.then(done)
|
|
178
|
-
.catch(
|
|
179
|
+
.catch(warnExists);
|
|
179
180
|
opt.output('start', 'Creating index for Session.userId');
|
|
180
|
-
await db.schema.createIndex('Session_userId_index').on('Session').column('userId').execute().then(done).catch(
|
|
181
|
+
await db.schema.createIndex('Session_userId_index').on('Session').column('userId').execute().then(done).catch(warnExists);
|
|
181
182
|
opt.output('start', 'Creating table VerificationToken');
|
|
182
183
|
await db.schema
|
|
183
184
|
.createTable('VerificationToken')
|
|
@@ -186,7 +187,7 @@ export async function init(opt) {
|
|
|
186
187
|
.addColumn('expires', 'timestamptz', col => col.notNull())
|
|
187
188
|
.execute()
|
|
188
189
|
.then(done)
|
|
189
|
-
.catch(
|
|
190
|
+
.catch(warnExists);
|
|
190
191
|
opt.output('start', 'Creating table Authenticator');
|
|
191
192
|
await db.schema
|
|
192
193
|
.createTable('Authenticator')
|
|
@@ -200,10 +201,15 @@ export async function init(opt) {
|
|
|
200
201
|
.addColumn('transports', 'text')
|
|
201
202
|
.execute()
|
|
202
203
|
.then(done)
|
|
203
|
-
.catch(
|
|
204
|
+
.catch(warnExists);
|
|
204
205
|
opt.output('start', 'Creating index for Authenticator.credentialID');
|
|
205
|
-
await db.schema.createIndex('Authenticator_credentialID_key').on('Authenticator').column('credentialID').execute().then(done).catch(
|
|
206
|
-
|
|
206
|
+
await db.schema.createIndex('Authenticator_credentialID_key').on('Authenticator').column('credentialID').execute().then(done).catch(warnExists);
|
|
207
|
+
for (const plugin of plugins) {
|
|
208
|
+
if (!plugin.db)
|
|
209
|
+
continue;
|
|
210
|
+
opt.output('plugin', plugin.name);
|
|
211
|
+
await plugin.db.init(opt, db, { warnExists, done });
|
|
212
|
+
}
|
|
207
213
|
}
|
|
208
214
|
catch (e_1) {
|
|
209
215
|
env_1.error = e_1;
|
|
@@ -220,6 +226,14 @@ export async function init(opt) {
|
|
|
220
226
|
*/
|
|
221
227
|
export async function uninstall(opt) {
|
|
222
228
|
_fixOutput(opt);
|
|
229
|
+
const db = connect();
|
|
230
|
+
for (const plugin of plugins) {
|
|
231
|
+
if (!plugin.db)
|
|
232
|
+
continue;
|
|
233
|
+
opt.output('plugin', plugin.name);
|
|
234
|
+
await plugin.db.remove(opt, db);
|
|
235
|
+
}
|
|
236
|
+
await db.destroy();
|
|
223
237
|
const _sql = (command, message) => run(opt, message, `sudo -u postgres psql -c "${command}"`);
|
|
224
238
|
await _sql('DROP DATABASE axium', 'Dropping database');
|
|
225
239
|
await _sql('REVOKE ALL PRIVILEGES ON SCHEMA public FROM axium', 'Revoking schema privileges');
|
|
@@ -231,6 +245,12 @@ export async function uninstall(opt) {
|
|
|
231
245
|
export async function wipe(opt) {
|
|
232
246
|
_fixOutput(opt);
|
|
233
247
|
const db = connect();
|
|
248
|
+
for (const plugin of plugins) {
|
|
249
|
+
if (!plugin.db)
|
|
250
|
+
continue;
|
|
251
|
+
opt.output('plugin', plugin.name);
|
|
252
|
+
await plugin.db.wipe(opt, db);
|
|
253
|
+
}
|
|
234
254
|
for (const table of ['User', 'Account', 'Session', 'VerificationToken', 'Authenticator']) {
|
|
235
255
|
opt.output('start', `Removing data from ${table}`);
|
|
236
256
|
await db.deleteFrom(table).execute();
|
package/dist/io.d.ts
CHANGED
|
@@ -25,10 +25,10 @@ export declare function run(opts: WithOutput & {
|
|
|
25
25
|
/** Yet another convenience function */
|
|
26
26
|
export declare function exit(message: string | Error, code?: number): never;
|
|
27
27
|
export declare function handleError(e: number | string | Error): void;
|
|
28
|
-
export type
|
|
28
|
+
export type OutputTag = 'debug' | 'info' | 'warn' | 'error' | 'start' | 'done' | 'plugin';
|
|
29
29
|
export interface Output {
|
|
30
|
-
(
|
|
31
|
-
(
|
|
30
|
+
(tag: 'done'): void;
|
|
31
|
+
(tag: Exclude<OutputTag, 'done'>, message: string): void;
|
|
32
32
|
}
|
|
33
33
|
export interface MaybeOutput {
|
|
34
34
|
output?: Output | null | false;
|
|
@@ -36,8 +36,8 @@ export interface MaybeOutput {
|
|
|
36
36
|
export interface WithOutput {
|
|
37
37
|
output: Output;
|
|
38
38
|
}
|
|
39
|
-
export declare function defaultOutput(
|
|
40
|
-
export declare function defaultOutput(
|
|
39
|
+
export declare function defaultOutput(tag: 'done'): void;
|
|
40
|
+
export declare function defaultOutput(tag: Exclude<OutputTag, 'done'>, message: string): void;
|
|
41
41
|
/**
|
|
42
42
|
* TS can't tell when we do this inline
|
|
43
43
|
* @internal
|
package/dist/io.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as fs from 'node:fs';
|
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path/posix';
|
|
6
6
|
import { styleText } from 'node:util';
|
|
7
|
-
import
|
|
7
|
+
import config from './config.js';
|
|
8
8
|
/**
|
|
9
9
|
* Find the Axium directory.
|
|
10
10
|
* This directory includes things like config files, secrets, etc.
|
|
@@ -81,15 +81,12 @@ export function handleError(e) {
|
|
|
81
81
|
else
|
|
82
82
|
exit(e);
|
|
83
83
|
}
|
|
84
|
-
export function defaultOutput(
|
|
85
|
-
switch (
|
|
86
|
-
case 'start':
|
|
87
|
-
process.stdout.write(message + '... ');
|
|
88
|
-
break;
|
|
84
|
+
export function defaultOutput(tag, message = '') {
|
|
85
|
+
switch (tag) {
|
|
89
86
|
case 'debug':
|
|
90
|
-
debug && output.debug(message);
|
|
87
|
+
config.debug && output.debug(message);
|
|
91
88
|
break;
|
|
92
|
-
case '
|
|
89
|
+
case 'info':
|
|
93
90
|
console.log(message);
|
|
94
91
|
break;
|
|
95
92
|
case 'warn':
|
|
@@ -98,9 +95,14 @@ export function defaultOutput(state, message = '') {
|
|
|
98
95
|
case 'error':
|
|
99
96
|
console.error(styleText('red', message));
|
|
100
97
|
break;
|
|
98
|
+
case 'start':
|
|
99
|
+
process.stdout.write(message + '... ');
|
|
100
|
+
break;
|
|
101
101
|
case 'done':
|
|
102
102
|
console.log('done.');
|
|
103
103
|
break;
|
|
104
|
+
case 'plugin':
|
|
105
|
+
console.log(styleText('whiteBright', 'Running plugin: ' + message));
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
/**
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
export declare const Plugin: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
version: z.ZodString;
|
|
6
|
+
description: z.ZodOptional<z.ZodString>;
|
|
7
|
+
statusText: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodString, z.ZodPromise<z.ZodString>]>>>;
|
|
8
|
+
db: z.ZodOptional<z.ZodObject<{
|
|
9
|
+
init: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>;
|
|
10
|
+
remove: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>;
|
|
11
|
+
wipe: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
init: (...args: unknown[]) => unknown;
|
|
14
|
+
remove: (...args: unknown[]) => unknown;
|
|
15
|
+
wipe: (...args: unknown[]) => unknown;
|
|
16
|
+
}, {
|
|
17
|
+
init: (...args: unknown[]) => unknown;
|
|
18
|
+
remove: (...args: unknown[]) => unknown;
|
|
19
|
+
wipe: (...args: unknown[]) => unknown;
|
|
20
|
+
}>>;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
name: string;
|
|
23
|
+
id: string;
|
|
24
|
+
version: string;
|
|
25
|
+
db?: {
|
|
26
|
+
init: (...args: unknown[]) => unknown;
|
|
27
|
+
remove: (...args: unknown[]) => unknown;
|
|
28
|
+
wipe: (...args: unknown[]) => unknown;
|
|
29
|
+
} | undefined;
|
|
30
|
+
description?: string | undefined;
|
|
31
|
+
statusText?: ((...args: unknown[]) => string | Promise<string>) | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
name: string;
|
|
34
|
+
id: string;
|
|
35
|
+
version: string;
|
|
36
|
+
db?: {
|
|
37
|
+
init: (...args: unknown[]) => unknown;
|
|
38
|
+
remove: (...args: unknown[]) => unknown;
|
|
39
|
+
wipe: (...args: unknown[]) => unknown;
|
|
40
|
+
} | undefined;
|
|
41
|
+
description?: string | undefined;
|
|
42
|
+
statusText?: ((...args: unknown[]) => string | Promise<string>) | undefined;
|
|
43
|
+
}>;
|
|
44
|
+
export interface Plugin extends z.infer<typeof Plugin> {
|
|
45
|
+
}
|
|
46
|
+
export declare const plugins: Set<Plugin>;
|
|
47
|
+
export declare function resolvePlugin(search: string): Plugin | undefined;
|
|
48
|
+
export declare function pluginText(plugin: Plugin): string;
|
|
49
|
+
export declare function loadPlugin(path: string): Promise<void>;
|
|
50
|
+
export declare function loadPlugins(dir: string): Promise<void>;
|
|
51
|
+
export declare function loadDefaultPlugins(): Promise<void>;
|
package/dist/plugins.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path/posix';
|
|
3
|
+
import { styleText } from 'node:util';
|
|
4
|
+
import * as z from 'zod';
|
|
5
|
+
import { findDir, output } from './io.js';
|
|
6
|
+
import { fromZodError } from 'zod-validation-error';
|
|
7
|
+
export const Plugin = z.object({
|
|
8
|
+
id: z.string(),
|
|
9
|
+
name: z.string(),
|
|
10
|
+
version: z.string(),
|
|
11
|
+
description: z.string().optional(),
|
|
12
|
+
statusText: z
|
|
13
|
+
.function()
|
|
14
|
+
.args()
|
|
15
|
+
.returns(z.union([z.string(), z.promise(z.string())]))
|
|
16
|
+
.optional(),
|
|
17
|
+
db: z
|
|
18
|
+
.object({
|
|
19
|
+
init: z.function(),
|
|
20
|
+
remove: z.function(),
|
|
21
|
+
wipe: z.function(),
|
|
22
|
+
})
|
|
23
|
+
.optional(),
|
|
24
|
+
});
|
|
25
|
+
export const plugins = new Set();
|
|
26
|
+
export function resolvePlugin(search) {
|
|
27
|
+
for (const plugin of plugins) {
|
|
28
|
+
if (plugin.name.startsWith(search) || plugin.id.startsWith(search))
|
|
29
|
+
return plugin;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function pluginText(plugin) {
|
|
33
|
+
return [
|
|
34
|
+
styleText('whiteBright', plugin.name),
|
|
35
|
+
plugin.id,
|
|
36
|
+
`Version: ${plugin.version}`,
|
|
37
|
+
`Description: ${plugin.description ?? styleText('dim', '(none)')}`,
|
|
38
|
+
`Status text integration: ${plugin.statusText ? styleText('whiteBright', 'yes') : styleText('yellow', 'no')}`,
|
|
39
|
+
`Database integration: ${plugin.db ? 'yes' : 'no'}`,
|
|
40
|
+
].join('\n');
|
|
41
|
+
}
|
|
42
|
+
export async function loadPlugin(path) {
|
|
43
|
+
path = resolve(path);
|
|
44
|
+
const stats = fs.statSync(path);
|
|
45
|
+
if (stats.isDirectory() || !['.js', '.mjs'].some(ext => path.endsWith(ext)))
|
|
46
|
+
return;
|
|
47
|
+
try {
|
|
48
|
+
const plugin = await Plugin.parseAsync(await import(path)).catch(e => {
|
|
49
|
+
throw fromZodError(e);
|
|
50
|
+
});
|
|
51
|
+
plugins.add(plugin);
|
|
52
|
+
output.debug(`Loaded plugin: "${plugin.name}" (${plugin.id}) ${plugin.version}`);
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
output.debug(`Failed to load plugin from ${path}: ${e}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function loadPlugins(dir) {
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
const files = fs.readdirSync(dir);
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
await loadPlugin(join(dir, file));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function loadDefaultPlugins() {
|
|
66
|
+
await loadPlugins(join(findDir(true), 'plugins'));
|
|
67
|
+
await loadPlugins(join(findDir(false), 'plugins'));
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"kysely": "^0.27.5",
|
|
47
47
|
"logzen": "^0.6.2",
|
|
48
48
|
"pg": "^8.14.1",
|
|
49
|
-
"utilium": "^2.
|
|
49
|
+
"utilium": "^2.3.0",
|
|
50
50
|
"zod-validation-error": "^3.4.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
package/web/auth.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { SvelteKitAuth } from '@auth/sveltekit';
|
|
|
2
2
|
import { createWriteStream } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path/posix';
|
|
4
4
|
import { getConfig } from '../dist/auth.js';
|
|
5
|
-
import
|
|
5
|
+
import config from '../dist/config.js';
|
|
6
6
|
import { findDir, logger } from '../dist/io.js';
|
|
7
7
|
import { allLogLevels } from 'logzen';
|
|
8
8
|
|
|
9
9
|
logger.attach(createWriteStream(join(findDir(false), 'server.log')), { output: allLogLevels });
|
|
10
|
-
|
|
10
|
+
config.loadDefaults();
|
|
11
11
|
|
|
12
12
|
export const { handle, signIn, signOut } = SvelteKitAuth(getConfig());
|
package/web/utils.ts
CHANGED
|
@@ -3,12 +3,12 @@ import type { ActionFailure, RequestEvent } from '@sveltejs/kit';
|
|
|
3
3
|
import { fail, redirect } from '@sveltejs/kit';
|
|
4
4
|
import type * as z from 'zod';
|
|
5
5
|
import { fromError } from 'zod-validation-error';
|
|
6
|
-
import
|
|
6
|
+
import config from '../dist/config.js';
|
|
7
7
|
|
|
8
8
|
export async function loadSession(event: RequestEvent): Promise<{ session: Session }> {
|
|
9
9
|
const session = await event.locals.auth();
|
|
10
10
|
if (!session) redirect(307, '/auth/signin');
|
|
11
|
-
if (!session.user.name && event.url.pathname != web.prefix + '/name') redirect(307, web.prefix + '/name');
|
|
11
|
+
if (!session.user.name && event.url.pathname != config.web.prefix + '/name') redirect(307, config.web.prefix + '/name');
|
|
12
12
|
return { session };
|
|
13
13
|
}
|
|
14
14
|
|