@axium/server 0.7.2 → 0.7.5

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/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Argument, Option, program } from 'commander';
3
+ import { randomBytes } from 'node:crypto';
3
4
  import { styleText } from 'node:util';
4
5
  import { getByString, isJSON, setByString } from 'utilium';
5
6
  import $pkg from '../package.json' with { type: 'json' };
@@ -24,6 +25,10 @@ program.hook('preAction', async function (_, action) {
24
25
  opt.force && output.warn('--force: Protections disabled.');
25
26
  if (opt.debug === false)
26
27
  config.set({ debug: false });
28
+ if (!config.auth.secret) {
29
+ config.save({ auth: { secret: process.env.AUTH_SECRET || randomBytes(32).toString('base64') } }, true);
30
+ output.debug('Auto-generated a new auth secret');
31
+ }
27
32
  });
28
33
  // Options shared by multiple (sub)commands
29
34
  const opts = {
@@ -98,33 +103,46 @@ axiumDB
98
103
  await db.wipe(opt).catch(exit);
99
104
  await db.database.destroy();
100
105
  });
101
- const axiumConfig = program.command('config').description('Manage the configuration').addOption(opts.global).option('-j, --json', 'values are JSON encoded');
106
+ const axiumConfig = program
107
+ .command('config')
108
+ .description('Manage the configuration')
109
+ .addOption(opts.global)
110
+ .option('-j, --json', 'values are JSON encoded')
111
+ .option('-r, --redact', 'Do not output sensitive values');
112
+ function configReplacer(opt) {
113
+ return (key, value) => {
114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
115
+ return opt.redact && ['password', 'secret'].includes(key) ? '[redacted]' : value;
116
+ };
117
+ }
102
118
  axiumConfig
103
119
  .command('dump')
104
120
  .description('Output the entire current configuration')
105
121
  .action(() => {
106
- const value = config;
107
- console.log(axiumConfig.optsWithGlobals().json ? JSON.stringify(value) : value);
122
+ const opt = axiumConfig.optsWithGlobals();
123
+ const value = config.plain();
124
+ console.log(opt.json ? JSON.stringify(value, configReplacer(opt), 4) : value);
108
125
  });
109
126
  axiumConfig
110
127
  .command('get')
111
128
  .description('Get a config value')
112
129
  .argument('<key>', 'the key to get')
113
130
  .action((key) => {
114
- const value = getByString(config, key);
115
- console.log(axiumConfig.optsWithGlobals().json ? JSON.stringify(value) : value);
131
+ const opt = axiumConfig.optsWithGlobals();
132
+ const value = getByString(config.plain(), key);
133
+ console.log(opt.json ? JSON.stringify(value, configReplacer(opt), 4) : value);
116
134
  });
117
135
  axiumConfig
118
136
  .command('set')
119
137
  .description('Set a config value. Note setting objects is not supported.')
120
138
  .argument('<key>', 'the key to set')
121
139
  .argument('<value>', 'the value')
122
- .action((key, value, opt) => {
123
- const useJSON = axiumConfig.optsWithGlobals().json;
124
- if (useJSON && !isJSON(value))
140
+ .action((key, value) => {
141
+ const opt = axiumConfig.optsWithGlobals();
142
+ if (opt.json && !isJSON(value))
125
143
  exit('Invalid JSON');
126
144
  const obj = {};
127
- setByString(obj, key, useJSON ? JSON.parse(value) : value);
145
+ setByString(obj, key, opt.json ? JSON.parse(value) : value);
128
146
  config.save(obj, opt.global);
129
147
  });
130
148
  axiumConfig
@@ -216,6 +234,7 @@ program
216
234
  .addOption(opts.force)
217
235
  .addOption(opts.host)
218
236
  .action(async (opt) => {
237
+ config.save({ auth: { secret: randomBytes(32).toString('base64') } }, true);
219
238
  await db.init({ ...opt, skip: opt.dbSkip }).catch(handleError);
220
239
  await restrictedPorts({ method: 'node-cap', action: 'enable' }).catch(handleError);
221
240
  });
package/dist/config.d.ts CHANGED
@@ -166,10 +166,12 @@ export declare const Schema: z.ZodObject<{
166
166
  export interface Config extends Record<string, unknown>, z.infer<typeof Schema> {
167
167
  }
168
168
  export declare const configFiles: Map<string, PartialRecursive<Config>>;
169
+ export declare function plainConfig(): Omit<Config, keyof typeof configShortcuts>;
169
170
  declare const configShortcuts: {
170
171
  findPath: typeof findConfigPath;
171
172
  load: typeof loadConfig;
172
173
  loadDefaults: typeof loadDefaultConfigs;
174
+ plain: typeof plainConfig;
173
175
  save: typeof saveConfig;
174
176
  saveTo: typeof saveConfigTo;
175
177
  set: typeof setConfig;
package/dist/config.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
2
  import { levelText } from 'logzen';
3
- import { readFileSync, writeFileSync } from 'node:fs';
4
- import { dirname, join } from 'node:path/posix';
5
- import { deepAssign } from 'utilium';
3
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { dirname, join, resolve } from 'node:path/posix';
5
+ import { deepAssign, omit } from 'utilium';
6
6
  import * as z from 'zod';
7
7
  import { findDir, logger, output } from './io.js';
8
8
  import { loadPlugin } from './plugins.js';
@@ -32,10 +32,14 @@ export const Schema = z
32
32
  })
33
33
  .passthrough();
34
34
  export const configFiles = new Map();
35
+ export function plainConfig() {
36
+ return omit(config, Object.keys(configShortcuts));
37
+ }
35
38
  const configShortcuts = {
36
39
  findPath: findConfigPath,
37
40
  load: loadConfig,
38
41
  loadDefaults: loadDefaultConfigs,
42
+ plain: plainConfig,
39
43
  save: saveConfig,
40
44
  saveTo: saveConfigTo,
41
45
  set: setConfig,
@@ -102,11 +106,14 @@ export async function loadConfig(path, options = {}) {
102
106
  for (const include of file.include ?? [])
103
107
  await loadConfig(join(dirname(path), include), { optional: true });
104
108
  for (const plugin of file.plugins ?? [])
105
- await loadPlugin(plugin);
109
+ await loadPlugin(plugin.startsWith('.') ? resolve(dirname(path), plugin) : plugin);
106
110
  }
107
111
  export async function loadDefaultConfigs() {
108
- await loadConfig(findConfigPath(true), { optional: true });
109
- await loadConfig(findConfigPath(false), { optional: true });
112
+ for (const path of [findConfigPath(true), findConfigPath(false)]) {
113
+ if (!existsSync(path))
114
+ writeFileSync(path, '{}');
115
+ await loadConfig(path, { optional: true });
116
+ }
110
117
  }
111
118
  /**
112
119
  * Update the current config and write the updated config to the appropriate file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/server",
3
- "version": "0.7.2",
3
+ "version": "0.7.5",
4
4
  "author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -44,7 +44,7 @@
44
44
  "bcryptjs": "^3.0.2",
45
45
  "commander": "^13.1.0",
46
46
  "kysely": "^0.27.5",
47
- "logzen": "^0.6.2",
47
+ "logzen": "^0.7.0",
48
48
  "pg": "^8.14.1",
49
49
  "utilium": "^2.3.0",
50
50
  "zod-validation-error": "^3.4.0"
@@ -1,41 +1,23 @@
1
1
  <script lang="ts">
2
- import { onMount } from 'svelte';
3
-
2
+ import light from './icons/light.svg';
3
+ import solid from './icons/solid.svg';
4
+ import regular from './icons/regular.svg';
5
+ const urls = { light, solid, regular };
4
6
  const { i } = $props();
5
7
 
6
- const withStyle = i.includes('/') ? i : 'solid/' + i;
7
- const href = `https://site-assets.fontawesome.com/releases/v6.7.2/svgs/${withStyle}.svg`;
8
-
9
- let content = $state('');
10
-
11
- // Fetch and inline the SVG content on component mount
12
- onMount(async () => {
13
- const res = await fetch(href);
14
-
15
- if (!res.ok) {
16
- console.error('Failed to fetch icon:', res.statusText);
17
- return;
18
- }
19
-
20
- const text = await res.text();
21
-
22
- const doc = new DOMParser().parseFromString(text, 'image/svg+xml');
23
- const errorNode = doc.querySelector('parsererror');
24
-
25
- if (errorNode || doc.documentElement?.nodeName != 'svg') {
26
- console.error('Invalid SVG');
27
- return;
28
- }
29
-
30
- content = text;
31
- });
8
+ const [style, id] = i.includes('/') ? i.split('/') : ['solid', i];
9
+ const url = urls[style];
32
10
  </script>
33
11
 
34
12
  <svelte:head>
35
- <link rel="preload" {href} />
13
+ <link rel="preload" href={url} />
36
14
  </svelte:head>
37
15
 
38
- <span>{@html content}</span>
16
+ <span>
17
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="1em" height="1em">
18
+ <use href="{url}#{id}" />
19
+ </svg>
20
+ </span>
39
21
 
40
22
  <style>
41
23
  span {