@axium/storage 0.7.8 → 0.7.10
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/hooks.d.ts +8 -0
- package/dist/{plugin.js → hooks.js} +5 -11
- package/dist/server.js +52 -52
- package/lib/List.svelte +1 -1
- package/lib/Usage.svelte +4 -2
- package/package.json +19 -15
- package/routes/files/shared/+page.svelte +2 -2
- package/routes/files/trash/+page.svelte +2 -2
- package/routes/files/usage/+page.svelte +5 -6
- package/dist/plugin.d.ts +0 -67
- package/styles/list.css +0 -50
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InitOptions, OpOptions } from '@axium/server/database';
|
|
2
|
+
import './common.js';
|
|
3
|
+
import './server.js';
|
|
4
|
+
export declare function statusText(): Promise<string>;
|
|
5
|
+
export declare function db_init(opt: InitOptions): Promise<void>;
|
|
6
|
+
export declare function db_wipe(opt: OpOptions): Promise<void>;
|
|
7
|
+
export declare function remove(opt: OpOptions): Promise<void>;
|
|
8
|
+
export declare function clean(opt: OpOptions): Promise<void>;
|
|
@@ -4,10 +4,9 @@ import config from '@axium/server/config';
|
|
|
4
4
|
import { count, createIndex, database, warnExists } from '@axium/server/database';
|
|
5
5
|
import { done, start } from '@axium/server/io';
|
|
6
6
|
import { sql } from 'kysely';
|
|
7
|
-
import pkg from '../package.json' with { type: 'json' };
|
|
8
7
|
import './common.js';
|
|
9
8
|
import './server.js';
|
|
10
|
-
async function statusText() {
|
|
9
|
+
export async function statusText() {
|
|
11
10
|
const { storage: items } = await count('storage');
|
|
12
11
|
const { size } = await database
|
|
13
12
|
.selectFrom('storage')
|
|
@@ -15,7 +14,7 @@ async function statusText() {
|
|
|
15
14
|
.executeTakeFirstOrThrow();
|
|
16
15
|
return `${items} items totaling ${formatBytes(Number(size))}`;
|
|
17
16
|
}
|
|
18
|
-
async function db_init(opt) {
|
|
17
|
+
export async function db_init(opt) {
|
|
19
18
|
start('Creating table storage');
|
|
20
19
|
await database.schema
|
|
21
20
|
.createTable('storage')
|
|
@@ -39,18 +38,18 @@ async function db_init(opt) {
|
|
|
39
38
|
await createIndex('storage', 'parentId');
|
|
40
39
|
await acl.createTable('storage');
|
|
41
40
|
}
|
|
42
|
-
async function db_wipe(opt) {
|
|
41
|
+
export async function db_wipe(opt) {
|
|
43
42
|
start('Removing data from user storage');
|
|
44
43
|
await database.deleteFrom('storage').execute().then(done);
|
|
45
44
|
await acl.wipeTable('storage');
|
|
46
45
|
}
|
|
47
|
-
async function remove(opt) {
|
|
46
|
+
export async function remove(opt) {
|
|
48
47
|
start('Dropping table storage');
|
|
49
48
|
await database.schema.dropTable('storage').execute();
|
|
50
49
|
await acl.dropTable('storage');
|
|
51
50
|
done();
|
|
52
51
|
}
|
|
53
|
-
async function clean(opt) {
|
|
52
|
+
export async function clean(opt) {
|
|
54
53
|
start('Removing expired trash items');
|
|
55
54
|
const nDaysAgo = new Date(Date.now() - 86400000 * config.storage.trash_duration);
|
|
56
55
|
await database
|
|
@@ -60,8 +59,3 @@ async function clean(opt) {
|
|
|
60
59
|
.executeTakeFirstOrThrow()
|
|
61
60
|
.then(done);
|
|
62
61
|
}
|
|
63
|
-
export default {
|
|
64
|
-
...pkg,
|
|
65
|
-
statusText,
|
|
66
|
-
hooks: { db_init, db_wipe, remove, clean },
|
|
67
|
-
};
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Permission } from '@axium/core
|
|
2
|
-
import { addEvent, audit
|
|
1
|
+
import { Permission, Severity } from '@axium/core';
|
|
2
|
+
import { addEvent, audit } from '@axium/server/audit';
|
|
3
3
|
import { checkAuthForItem, checkAuthForUser, getSessionAndUser } from '@axium/server/auth';
|
|
4
4
|
import { addConfigDefaults, config } from '@axium/server/config';
|
|
5
5
|
import { database, expectedTypes } from '@axium/server/database';
|
|
@@ -113,19 +113,19 @@ export async function deleteRecursive(itemId, deleteSelf) {
|
|
|
113
113
|
addRoute({
|
|
114
114
|
path: '/api/storage/item/:id',
|
|
115
115
|
params: { id: z.uuid() },
|
|
116
|
-
async GET(
|
|
116
|
+
async GET(request, params) {
|
|
117
117
|
if (!config.storage.enabled)
|
|
118
118
|
error(503, 'User storage is disabled');
|
|
119
|
-
const itemId =
|
|
120
|
-
const { item } = await checkAuthForItem(
|
|
119
|
+
const itemId = params.id;
|
|
120
|
+
const { item } = await checkAuthForItem(request, 'storage', itemId, Permission.Read);
|
|
121
121
|
return parseItem(item);
|
|
122
122
|
},
|
|
123
|
-
async PATCH(
|
|
123
|
+
async PATCH(request, params) {
|
|
124
124
|
if (!config.storage.enabled)
|
|
125
125
|
error(503, 'User storage is disabled');
|
|
126
|
-
const itemId =
|
|
127
|
-
const body = await parseBody(
|
|
128
|
-
await checkAuthForItem(
|
|
126
|
+
const itemId = params.id;
|
|
127
|
+
const body = await parseBody(request, StorageItemUpdate);
|
|
128
|
+
await checkAuthForItem(request, 'storage', itemId, Permission.Manage);
|
|
129
129
|
const values = {};
|
|
130
130
|
if ('publicPermission' in body)
|
|
131
131
|
values.publicPermission = body.publicPermission;
|
|
@@ -145,11 +145,11 @@ addRoute({
|
|
|
145
145
|
.executeTakeFirstOrThrow()
|
|
146
146
|
.catch(withError('Could not update item')));
|
|
147
147
|
},
|
|
148
|
-
async DELETE(
|
|
148
|
+
async DELETE(request, params) {
|
|
149
149
|
if (!config.storage.enabled)
|
|
150
150
|
error(503, 'User storage is disabled');
|
|
151
|
-
const itemId =
|
|
152
|
-
const auth = await checkAuthForItem(
|
|
151
|
+
const itemId = params.id;
|
|
152
|
+
const auth = await checkAuthForItem(request, 'storage', itemId, Permission.Manage);
|
|
153
153
|
const item = parseItem(auth.item);
|
|
154
154
|
await deleteRecursive(itemId, item.type != 'inode/directory');
|
|
155
155
|
return item;
|
|
@@ -158,11 +158,11 @@ addRoute({
|
|
|
158
158
|
addRoute({
|
|
159
159
|
path: '/api/storage/directory/:id',
|
|
160
160
|
params: { id: z.uuid() },
|
|
161
|
-
async GET(
|
|
161
|
+
async GET(request, params) {
|
|
162
162
|
if (!config.storage.enabled)
|
|
163
163
|
error(503, 'User storage is disabled');
|
|
164
|
-
const itemId =
|
|
165
|
-
const { item } = await checkAuthForItem(
|
|
164
|
+
const itemId = params.id;
|
|
165
|
+
const { item } = await checkAuthForItem(request, 'storage', itemId, Permission.Read);
|
|
166
166
|
if (item.type != 'inode/directory')
|
|
167
167
|
error(409, 'Item is not a directory');
|
|
168
168
|
const items = await database
|
|
@@ -176,20 +176,20 @@ addRoute({
|
|
|
176
176
|
});
|
|
177
177
|
addRoute({
|
|
178
178
|
path: '/raw/storage',
|
|
179
|
-
async PUT(
|
|
179
|
+
async PUT(request) {
|
|
180
180
|
if (!config.storage.enabled)
|
|
181
181
|
error(503, 'User storage is disabled');
|
|
182
|
-
const token = getToken(
|
|
182
|
+
const token = getToken(request);
|
|
183
183
|
if (!token)
|
|
184
184
|
error(401, 'Missing session token');
|
|
185
185
|
const { userId } = await getSessionAndUser(token).catch(withError('Invalid session token', 401));
|
|
186
186
|
const [usage, limits] = await Promise.all([currentUsage(userId), getLimits(userId)]).catch(withError('Could not fetch usage and/or limits'));
|
|
187
|
-
const name =
|
|
187
|
+
const name = request.headers.get('x-name');
|
|
188
188
|
if (!name)
|
|
189
189
|
error(400, 'Missing name header');
|
|
190
190
|
if (name.length > 255)
|
|
191
191
|
error(400, 'Name is too long');
|
|
192
|
-
const maybeParentId =
|
|
192
|
+
const maybeParentId = request.headers.get('x-parent');
|
|
193
193
|
const parentId = maybeParentId
|
|
194
194
|
? await z
|
|
195
195
|
.uuid()
|
|
@@ -197,22 +197,22 @@ addRoute({
|
|
|
197
197
|
.catch(() => error(400, 'Invalid parent ID'))
|
|
198
198
|
: null;
|
|
199
199
|
if (parentId)
|
|
200
|
-
await checkAuthForItem(
|
|
201
|
-
const size = Number(
|
|
200
|
+
await checkAuthForItem(request, 'storage', parentId, Permission.Edit);
|
|
201
|
+
const size = Number(request.headers.get('content-length'));
|
|
202
202
|
if (Number.isNaN(size))
|
|
203
203
|
error(411, 'Missing or invalid content length header');
|
|
204
|
-
if (usage.items >= limits.user_items)
|
|
204
|
+
if (limits.user_items && usage.items >= limits.user_items)
|
|
205
205
|
error(409, 'Too many items');
|
|
206
|
-
if ((usage.bytes + size) / 1_000_000 >= limits.user_size)
|
|
206
|
+
if (limits.user_size && (usage.bytes + size) / 1_000_000 >= limits.user_size)
|
|
207
207
|
error(413, 'Not enough space');
|
|
208
|
-
if (size > limits.item_size * 1_000_000)
|
|
208
|
+
if (limits.item_size && size > limits.item_size * 1_000_000)
|
|
209
209
|
error(413, 'File size exceeds maximum size');
|
|
210
|
-
const content = await
|
|
210
|
+
const content = await request.bytes();
|
|
211
211
|
if (content.byteLength > size) {
|
|
212
212
|
await audit('storage_size_mismatch', userId, { item: null });
|
|
213
213
|
error(400, 'Content length does not match size header');
|
|
214
214
|
}
|
|
215
|
-
const type =
|
|
215
|
+
const type = request.headers.get('content-type') || 'application/octet-stream';
|
|
216
216
|
const isDirectory = type == 'inode/directory';
|
|
217
217
|
if (isDirectory && size > 0)
|
|
218
218
|
error(400, 'Directories can not have content');
|
|
@@ -260,11 +260,11 @@ addRoute({
|
|
|
260
260
|
addRoute({
|
|
261
261
|
path: '/raw/storage/:id',
|
|
262
262
|
params: { id: z.uuid() },
|
|
263
|
-
async GET(
|
|
263
|
+
async GET(request, params) {
|
|
264
264
|
if (!config.storage.enabled)
|
|
265
265
|
error(503, 'User storage is disabled');
|
|
266
|
-
const itemId =
|
|
267
|
-
const { item } = await checkAuthForItem(
|
|
266
|
+
const itemId = params.id;
|
|
267
|
+
const { item } = await checkAuthForItem(request, 'storage', itemId, Permission.Read);
|
|
268
268
|
if (item.trashedAt)
|
|
269
269
|
error(410, 'Trashed items can not be downloaded');
|
|
270
270
|
const content = new Uint8Array(readFileSync(join(config.storage.data, item.id)));
|
|
@@ -275,31 +275,31 @@ addRoute({
|
|
|
275
275
|
},
|
|
276
276
|
});
|
|
277
277
|
},
|
|
278
|
-
async POST(
|
|
278
|
+
async POST(request, params) {
|
|
279
279
|
if (!config.storage.enabled)
|
|
280
280
|
error(503, 'User storage is disabled');
|
|
281
|
-
const itemId =
|
|
282
|
-
const { item, session } = await checkAuthForItem(
|
|
281
|
+
const itemId = params.id;
|
|
282
|
+
const { item, session } = await checkAuthForItem(request, 'storage', itemId, Permission.Edit);
|
|
283
283
|
if (item.immutable)
|
|
284
284
|
error(405, 'Item is immutable');
|
|
285
285
|
if (item.type == 'inode/directory')
|
|
286
286
|
error(409, 'Directories do not have content');
|
|
287
287
|
if (item.trashedAt)
|
|
288
288
|
error(410, 'Trashed items can not be changed');
|
|
289
|
-
const type =
|
|
289
|
+
const type = request.headers.get('content-type') || 'application/octet-stream';
|
|
290
290
|
if (type != item.type) {
|
|
291
291
|
await audit('storage_type_mismatch', session?.userId, { item: item.id });
|
|
292
292
|
error(400, 'Content type does not match existing item type');
|
|
293
293
|
}
|
|
294
|
-
const size = Number(
|
|
294
|
+
const size = Number(request.headers.get('content-length'));
|
|
295
295
|
if (Number.isNaN(size))
|
|
296
296
|
error(411, 'Missing or invalid content length header');
|
|
297
297
|
const [usage, limits] = await Promise.all([currentUsage(item.userId), getLimits(item.userId)]).catch(withError('Could not fetch usage and/or limits'));
|
|
298
|
-
if ((usage.bytes + size - item.size) / 1_000_000 >= limits.user_size)
|
|
298
|
+
if (limits.user_size && (usage.bytes + size - item.size) / 1_000_000 >= limits.user_size)
|
|
299
299
|
error(413, 'Not enough space');
|
|
300
|
-
if (size > limits.item_size * 1_000_000)
|
|
300
|
+
if (limits.item_size && size > limits.item_size * 1_000_000)
|
|
301
301
|
error(413, 'File size exceeds maximum size');
|
|
302
|
-
const content = await
|
|
302
|
+
const content = await request.bytes();
|
|
303
303
|
if (content.byteLength > size) {
|
|
304
304
|
await audit('storage_size_mismatch', session?.userId, { item: item.id });
|
|
305
305
|
error(400, 'Actual content length does not match header');
|
|
@@ -326,19 +326,19 @@ addRoute({
|
|
|
326
326
|
addRoute({
|
|
327
327
|
path: '/api/users/:id/storage',
|
|
328
328
|
params: { id: z.uuid() },
|
|
329
|
-
async OPTIONS(
|
|
329
|
+
async OPTIONS(request, params) {
|
|
330
330
|
if (!config.storage.enabled)
|
|
331
331
|
error(503, 'User storage is disabled');
|
|
332
|
-
const userId =
|
|
333
|
-
await checkAuthForUser(
|
|
332
|
+
const userId = params.id;
|
|
333
|
+
await checkAuthForUser(request, userId);
|
|
334
334
|
const [usage, limits] = await Promise.all([currentUsage(userId), getLimits(userId)]).catch(withError('Could not fetch data'));
|
|
335
335
|
return { usage, limits };
|
|
336
336
|
},
|
|
337
|
-
async GET(
|
|
337
|
+
async GET(request, params) {
|
|
338
338
|
if (!config.storage.enabled)
|
|
339
339
|
error(503, 'User storage is disabled');
|
|
340
|
-
const userId =
|
|
341
|
-
await checkAuthForUser(
|
|
340
|
+
const userId = params.id;
|
|
341
|
+
await checkAuthForUser(request, userId);
|
|
342
342
|
const [items, usage, limits] = await Promise.all([
|
|
343
343
|
database.selectFrom('storage').where('userId', '=', userId).where('trashedAt', 'is', null).selectAll().execute(),
|
|
344
344
|
currentUsage(userId),
|
|
@@ -350,11 +350,11 @@ addRoute({
|
|
|
350
350
|
addRoute({
|
|
351
351
|
path: '/api/users/:id/storage/root',
|
|
352
352
|
params: { id: z.uuid() },
|
|
353
|
-
async GET(
|
|
353
|
+
async GET(request, params) {
|
|
354
354
|
if (!config.storage.enabled)
|
|
355
355
|
error(503, 'User storage is disabled');
|
|
356
|
-
const userId =
|
|
357
|
-
await checkAuthForUser(
|
|
356
|
+
const userId = params.id;
|
|
357
|
+
await checkAuthForUser(request, userId);
|
|
358
358
|
const items = await database
|
|
359
359
|
.selectFrom('storage')
|
|
360
360
|
.where('userId', '=', userId)
|
|
@@ -376,11 +376,11 @@ function existsInACL(column, userId) {
|
|
|
376
376
|
addRoute({
|
|
377
377
|
path: '/api/users/:id/storage/shared',
|
|
378
378
|
params: { id: z.uuid() },
|
|
379
|
-
async GET(
|
|
379
|
+
async GET(request, params) {
|
|
380
380
|
if (!config.storage.enabled)
|
|
381
381
|
error(503, 'User storage is disabled');
|
|
382
|
-
const userId =
|
|
383
|
-
await checkAuthForUser(
|
|
382
|
+
const userId = params.id;
|
|
383
|
+
await checkAuthForUser(request, userId);
|
|
384
384
|
const items = await database
|
|
385
385
|
.selectFrom('storage as item')
|
|
386
386
|
.selectAll('item')
|
|
@@ -395,11 +395,11 @@ addRoute({
|
|
|
395
395
|
addRoute({
|
|
396
396
|
path: '/api/users/:id/storage/trash',
|
|
397
397
|
params: { id: z.uuid() },
|
|
398
|
-
async GET(
|
|
398
|
+
async GET(request, params) {
|
|
399
399
|
if (!config.storage.enabled)
|
|
400
400
|
error(503, 'User storage is disabled');
|
|
401
|
-
const userId =
|
|
402
|
-
await checkAuthForUser(
|
|
401
|
+
const userId = params.id;
|
|
402
|
+
await checkAuthForUser(request, userId);
|
|
403
403
|
const items = await database
|
|
404
404
|
.selectFrom('storage')
|
|
405
405
|
.where('userId', '=', userId)
|
package/lib/List.svelte
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { goto } from '$app/navigation';
|
|
3
3
|
import { FormDialog, Icon } from '@axium/client/components';
|
|
4
|
+
import '@axium/client/styles/list';
|
|
4
5
|
import { formatBytes } from '@axium/core/format';
|
|
5
6
|
import { forMime as iconForMime } from '@axium/core/icons';
|
|
6
7
|
import { getDirectoryMetadata, updateItemMetadata } from '@axium/storage/client';
|
|
7
8
|
import type { StorageItemMetadata } from '@axium/storage/common';
|
|
8
|
-
import '../styles/list.css';
|
|
9
9
|
|
|
10
10
|
let {
|
|
11
11
|
items = $bindable(),
|
package/lib/Usage.svelte
CHANGED
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
<p>
|
|
15
15
|
<a href="/files/usage">
|
|
16
16
|
<NumberBar
|
|
17
|
-
max={info.limits.user_size * 1_000_000}
|
|
17
|
+
max={info.limits.user_size && info.limits.user_size * 1_000_000}
|
|
18
18
|
value={info.usage.bytes}
|
|
19
|
-
text="Using {formatBytes(info.usage.bytes)}
|
|
19
|
+
text="Using {formatBytes(info.usage.bytes)} {!info.limits.user_size
|
|
20
|
+
? ''
|
|
21
|
+
: 'of ' + formatBytes(info.limits.user_size * 1_000_000)}"
|
|
20
22
|
/>
|
|
21
23
|
</a>
|
|
22
24
|
</p>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/storage",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"author": "James Prevett <axium@jamespre.dev>
|
|
3
|
+
"version": "0.7.10",
|
|
4
|
+
"author": "James Prevett <axium@jamespre.dev>",
|
|
5
5
|
"description": "User file storage for Axium",
|
|
6
6
|
"funding": {
|
|
7
7
|
"type": "individual",
|
|
@@ -27,20 +27,19 @@
|
|
|
27
27
|
"./components/*": "./lib/*.svelte",
|
|
28
28
|
"./styles/*": "./styles/*.css"
|
|
29
29
|
},
|
|
30
|
-
"routes": "routes",
|
|
31
30
|
"files": [
|
|
32
31
|
"dist",
|
|
33
32
|
"lib",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
33
|
+
"build",
|
|
34
|
+
"routes"
|
|
36
35
|
],
|
|
37
36
|
"scripts": {
|
|
38
37
|
"build": "tsc"
|
|
39
38
|
},
|
|
40
39
|
"peerDependencies": {
|
|
41
|
-
"@axium/client": ">=0.
|
|
42
|
-
"@axium/core": ">=0.
|
|
43
|
-
"@axium/server": ">=0.
|
|
40
|
+
"@axium/client": ">=0.5.0",
|
|
41
|
+
"@axium/core": ">=0.8.0",
|
|
42
|
+
"@axium/server": ">=0.25.0",
|
|
44
43
|
"@sveltejs/kit": "^2.27.3",
|
|
45
44
|
"utilium": "^2.3.8"
|
|
46
45
|
},
|
|
@@ -48,11 +47,16 @@
|
|
|
48
47
|
"blakejs": "^1.2.1",
|
|
49
48
|
"zod": "^4.0.5"
|
|
50
49
|
},
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
"axium": {
|
|
51
|
+
"http_handler": "./build/handler.js",
|
|
52
|
+
"hooks": "./dist/hooks.js",
|
|
53
|
+
"routes": "./routes",
|
|
54
|
+
"apps": [
|
|
55
|
+
{
|
|
56
|
+
"id": "files",
|
|
57
|
+
"name": "Files",
|
|
58
|
+
"icon": "folders"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
58
62
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { Icon } from '@axium/client/components';
|
|
3
|
+
import '@axium/client/styles/list';
|
|
2
4
|
import { formatBytes } from '@axium/core/format';
|
|
3
5
|
import { forMime as iconForMime } from '@axium/core/icons';
|
|
4
|
-
import { Icon } from '@axium/client/components';
|
|
5
|
-
import '@axium/storage/styles/list';
|
|
6
6
|
import type { PageProps } from './$types';
|
|
7
7
|
|
|
8
8
|
const { data }: PageProps = $props();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { FormDialog, Icon } from '@axium/client/components';
|
|
3
|
+
import '@axium/client/styles/list';
|
|
2
4
|
import { formatBytes } from '@axium/core/format';
|
|
3
5
|
import { forMime as iconForMime } from '@axium/core/icons';
|
|
4
|
-
import { FormDialog, Icon } from '@axium/client/components';
|
|
5
6
|
import { deleteItem, updateItemMetadata } from '@axium/storage/client';
|
|
6
|
-
import '@axium/storage/styles/list';
|
|
7
7
|
import type { PageProps } from './$types';
|
|
8
8
|
|
|
9
9
|
const { data }: PageProps = $props();
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { Icon, NumberBar } from '@axium/client/components';
|
|
2
3
|
import { formatBytes } from '@axium/core/format';
|
|
3
|
-
import { forMime } from '@axium/core/icons';
|
|
4
|
-
import { FormDialog, Icon, NumberBar } from '@axium/client/components';
|
|
5
|
-
import { deleteItem, updateItemMetadata } from '@axium/storage/client';
|
|
6
|
-
import type { StorageItemUpdate } from '@axium/storage/common';
|
|
7
4
|
import { StorageList } from '@axium/storage/components';
|
|
8
|
-
import '@axium/
|
|
5
|
+
import '@axium/client/styles/list';
|
|
9
6
|
|
|
10
7
|
const { data } = $props();
|
|
11
8
|
const { limits } = data.info;
|
|
@@ -14,7 +11,9 @@
|
|
|
14
11
|
const usage = $state(data.info.usage);
|
|
15
12
|
|
|
16
13
|
let dialogs = $state<Record<string, HTMLDialogElement>>({});
|
|
17
|
-
let barText = $derived(
|
|
14
|
+
let barText = $derived(
|
|
15
|
+
`Using ${formatBytes(usage?.bytes)} ${limits.user_size ? 'of ' + formatBytes(limits.user_size * 1_000_000) : ''}`
|
|
16
|
+
);
|
|
18
17
|
</script>
|
|
19
18
|
|
|
20
19
|
<svelte:head>
|
package/dist/plugin.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { InitOptions, OpOptions } from '@axium/server/database';
|
|
2
|
-
import './common.js';
|
|
3
|
-
import './server.js';
|
|
4
|
-
declare function statusText(): Promise<string>;
|
|
5
|
-
declare function db_init(opt: InitOptions): Promise<void>;
|
|
6
|
-
declare function db_wipe(opt: OpOptions): Promise<void>;
|
|
7
|
-
declare function remove(opt: OpOptions): Promise<void>;
|
|
8
|
-
declare function clean(opt: OpOptions): Promise<void>;
|
|
9
|
-
declare const _default: {
|
|
10
|
-
statusText: typeof statusText;
|
|
11
|
-
hooks: {
|
|
12
|
-
db_init: typeof db_init;
|
|
13
|
-
db_wipe: typeof db_wipe;
|
|
14
|
-
remove: typeof remove;
|
|
15
|
-
clean: typeof clean;
|
|
16
|
-
};
|
|
17
|
-
name: string;
|
|
18
|
-
version: string;
|
|
19
|
-
author: string;
|
|
20
|
-
description: string;
|
|
21
|
-
funding: {
|
|
22
|
-
type: string;
|
|
23
|
-
url: string;
|
|
24
|
-
};
|
|
25
|
-
license: string;
|
|
26
|
-
repository: {
|
|
27
|
-
type: string;
|
|
28
|
-
url: string;
|
|
29
|
-
};
|
|
30
|
-
homepage: string;
|
|
31
|
-
bugs: {
|
|
32
|
-
url: string;
|
|
33
|
-
};
|
|
34
|
-
type: string;
|
|
35
|
-
main: string;
|
|
36
|
-
types: string;
|
|
37
|
-
exports: {
|
|
38
|
-
".": string;
|
|
39
|
-
"./*": string;
|
|
40
|
-
"./sidebar": string;
|
|
41
|
-
"./components": string;
|
|
42
|
-
"./components/*": string;
|
|
43
|
-
"./styles/*": string;
|
|
44
|
-
};
|
|
45
|
-
routes: string;
|
|
46
|
-
files: string[];
|
|
47
|
-
scripts: {
|
|
48
|
-
build: string;
|
|
49
|
-
};
|
|
50
|
-
peerDependencies: {
|
|
51
|
-
"@axium/client": string;
|
|
52
|
-
"@axium/core": string;
|
|
53
|
-
"@axium/server": string;
|
|
54
|
-
"@sveltejs/kit": string;
|
|
55
|
-
utilium: string;
|
|
56
|
-
};
|
|
57
|
-
dependencies: {
|
|
58
|
-
blakejs: string;
|
|
59
|
-
zod: string;
|
|
60
|
-
};
|
|
61
|
-
apps: {
|
|
62
|
-
id: string;
|
|
63
|
-
name: string;
|
|
64
|
-
icon: string;
|
|
65
|
-
}[];
|
|
66
|
-
};
|
|
67
|
-
export default _default;
|
package/styles/list.css
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
.list {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-direction: column;
|
|
4
|
-
padding: 0.5em;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.list-header {
|
|
8
|
-
font-weight: bold;
|
|
9
|
-
border-bottom: 1.5px solid var(--fg-accent);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.list-item-container {
|
|
13
|
-
text-decoration: none;
|
|
14
|
-
color: inherit;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.list-item {
|
|
18
|
-
display: grid;
|
|
19
|
-
grid-template-columns: 1em 4fr 15em 5em repeat(3, 1em);
|
|
20
|
-
align-items: center;
|
|
21
|
-
gap: 1em;
|
|
22
|
-
padding: 0.5em;
|
|
23
|
-
overflow: hidden;
|
|
24
|
-
text-wrap: nowrap;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.list-item:not(.list-header, :first-child) {
|
|
28
|
-
border-top: 1px solid var(--fg-accent);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.list-item:not(.list-header):hover {
|
|
32
|
-
background-color: var(--bg-alt);
|
|
33
|
-
cursor: pointer;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
p.list-empty {
|
|
37
|
-
text-align: center;
|
|
38
|
-
color: #888;
|
|
39
|
-
margin-top: 1em;
|
|
40
|
-
font-style: italic;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.list-item .action {
|
|
44
|
-
visibility: hidden;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.list-item:hover .action {
|
|
48
|
-
visibility: visible;
|
|
49
|
-
cursor: pointer;
|
|
50
|
-
}
|