@axium/storage 0.14.0 → 0.14.2

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.
@@ -1,8 +1,14 @@
1
1
  import { getConfig, Severity } from '@axium/core';
2
2
  import { addEvent } from '@axium/server/audit';
3
+ import { statfsSync } from 'node:fs';
3
4
  import * as z from 'zod';
4
5
  import '../polyfills.js';
6
+ import { getTotalUse } from './db.js';
5
7
  export const defaultCASMime = [/video\/.*/, /audio\/.*/];
8
+ function getSystemAvailable() {
9
+ const { bavail, bsize } = statfsSync(getConfig('@axium/storage').data, { bigint: true });
10
+ return (bavail * bsize) / 1000000n;
11
+ }
6
12
  addEvent({
7
13
  source: '@axium/storage',
8
14
  name: 'storage_type_mismatch',
@@ -24,11 +30,26 @@ let _getLimits = null;
24
30
  export function useLimits(handler) {
25
31
  _getLimits = handler;
26
32
  }
33
+ let _cachedUnlimited, _cachedTime = 0;
34
+ /**
35
+ * Used when there is no user limit, that way users have an idea of how close they are to filling up system storage.
36
+ * @returns The maximum size that we can use in MB
37
+ */
38
+ async function _unlimitedLimit() {
39
+ if (_cachedUnlimited && Date.now() - _cachedTime < 300_000)
40
+ return _cachedUnlimited;
41
+ _cachedUnlimited = getSystemAvailable() + (await getTotalUse()) / 1000000n;
42
+ _cachedTime = Date.now();
43
+ return _cachedUnlimited;
44
+ }
27
45
  export async function getLimits(userId) {
46
+ let limits;
28
47
  try {
29
- return await _getLimits(userId);
48
+ limits = await _getLimits(userId);
30
49
  }
31
50
  catch {
32
- return getConfig('@axium/storage').limits;
51
+ limits = structuredClone(getConfig('@axium/storage').limits);
33
52
  }
53
+ limits.user_size ||= Number(await _unlimitedLimit());
54
+ return limits;
34
55
  }
@@ -42,3 +42,4 @@ export declare function getRecursive(this: {
42
42
  }>;
43
43
  export declare function getRecursiveIds(...ids: string[]): AsyncGenerator<string>;
44
44
  export declare function deleteRecursive(deleteSelf: boolean, ...itemId: string[]): Promise<void>;
45
+ export declare function getTotalUse(): Promise<bigint>;
package/dist/server/db.js CHANGED
@@ -64,3 +64,10 @@ export async function deleteRecursive(deleteSelf, ...itemId) {
64
64
  for (const id of toDelete)
65
65
  unlinkSync(join(getConfig('@axium/storage').data, id));
66
66
  }
67
+ export async function getTotalUse() {
68
+ const { size } = await database
69
+ .selectFrom('storage')
70
+ .select(eb => eb.fn.sum('size').as('size'))
71
+ .executeTakeFirstOrThrow();
72
+ return BigInt(size);
73
+ }
@@ -5,15 +5,13 @@ import { count, database } from '@axium/server/database';
5
5
  import { mkdirSync } from 'node:fs';
6
6
  import '../common.js';
7
7
  import './index.js';
8
+ import { getTotalUse } from './db.js';
8
9
  export function load() {
9
10
  mkdirSync(getConfig('@axium/storage').data, { recursive: true });
10
11
  }
11
12
  export async function statusText() {
12
13
  const { storage: items } = await count('storage');
13
- const { size } = await database
14
- .selectFrom('storage')
15
- .select(eb => eb.fn.sum('size').as('size'))
16
- .executeTakeFirstOrThrow();
14
+ const size = await getTotalUse();
17
15
  return `${items} items totaling ${formatBytes(Number(size))}`;
18
16
  }
19
17
  export async function clean(opt) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/storage",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "description": "User file storage for Axium",
6
6
  "funding": {