@axium/storage 0.13.0 → 0.13.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.
package/dist/common.d.ts CHANGED
@@ -1,16 +1,4 @@
1
1
  import * as z from 'zod';
2
- export declare const StoragePublicConfig: z.ZodObject<{
3
- batch: z.ZodObject<{
4
- enabled: z.ZodBoolean;
5
- max_items: z.ZodNumber;
6
- max_item_size: z.ZodNumber;
7
- }, z.core.$strip>;
8
- chunk: z.ZodBoolean;
9
- max_transfer_size: z.ZodNumber;
10
- max_chunks: z.ZodNumber;
11
- }, z.core.$strip>;
12
- export interface StoragePublicConfig extends z.infer<typeof StoragePublicConfig> {
13
- }
14
2
  /**
15
3
  * An update to file metadata.
16
4
  */
@@ -40,15 +28,15 @@ export interface StorageItemMetadata<T extends Record<string, unknown> = Record<
40
28
  }
41
29
  export declare const syncProtocolVersion = 0;
42
30
  export declare const StorageLimits: z.ZodObject<{
43
- item_size: z.ZodNumber;
44
- user_items: z.ZodNumber;
45
- user_size: z.ZodNumber;
31
+ item_size: z.ZodInt;
32
+ user_items: z.ZodInt;
33
+ user_size: z.ZodInt;
46
34
  }, z.core.$strip>;
47
35
  export interface StorageLimits extends z.infer<typeof StorageLimits> {
48
36
  }
49
37
  export declare const StorageStats: z.ZodObject<{
50
- usedBytes: z.ZodNumber;
51
- itemCount: z.ZodNumber;
38
+ usedBytes: z.ZodInt;
39
+ itemCount: z.ZodInt;
52
40
  lastModified: z.ZodCoercedDate<unknown>;
53
41
  lastTrashed: z.ZodNullable<z.ZodCoercedDate<unknown>>;
54
42
  }, z.core.$strip>;
@@ -56,12 +44,12 @@ export interface StorageStats extends z.infer<typeof StorageStats> {
56
44
  }
57
45
  export declare const UserStorageInfo: z.ZodObject<{
58
46
  limits: z.ZodObject<{
59
- item_size: z.ZodNumber;
60
- user_items: z.ZodNumber;
61
- user_size: z.ZodNumber;
47
+ item_size: z.ZodInt;
48
+ user_items: z.ZodInt;
49
+ user_size: z.ZodInt;
62
50
  }, z.core.$strip>;
63
- usedBytes: z.ZodNumber;
64
- itemCount: z.ZodNumber;
51
+ usedBytes: z.ZodInt;
52
+ itemCount: z.ZodInt;
65
53
  lastModified: z.ZodCoercedDate<unknown>;
66
54
  lastTrashed: z.ZodNullable<z.ZodCoercedDate<unknown>>;
67
55
  }, z.core.$strip>;
@@ -84,12 +72,12 @@ export declare const UserStorage: z.ZodObject<{
84
72
  metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
85
73
  }, z.core.$strip>>;
86
74
  limits: z.ZodObject<{
87
- item_size: z.ZodNumber;
88
- user_items: z.ZodNumber;
89
- user_size: z.ZodNumber;
75
+ item_size: z.ZodInt;
76
+ user_items: z.ZodInt;
77
+ user_size: z.ZodInt;
90
78
  }, z.core.$strip>;
91
- usedBytes: z.ZodNumber;
92
- itemCount: z.ZodNumber;
79
+ usedBytes: z.ZodInt;
80
+ itemCount: z.ZodInt;
93
81
  lastModified: z.ZodCoercedDate<unknown>;
94
82
  lastTrashed: z.ZodNullable<z.ZodCoercedDate<unknown>>;
95
83
  }, z.core.$strip>;
@@ -122,16 +110,57 @@ export declare const StorageBatchUpdate: z.ZodObject<{
122
110
  }, z.core.$strip>;
123
111
  export interface StorageBatchUpdate extends z.infer<typeof StorageBatchUpdate> {
124
112
  }
113
+ export declare const StoragePublicConfig: z.ZodObject<{
114
+ batch: z.ZodObject<{
115
+ enabled: z.ZodBoolean;
116
+ max_items: z.ZodInt;
117
+ max_item_size: z.ZodInt;
118
+ }, z.core.$strip>;
119
+ chunk: z.ZodBoolean;
120
+ max_transfer_size: z.ZodInt;
121
+ max_chunks: z.ZodInt;
122
+ }, z.core.$strip>;
123
+ export interface StoragePublicConfig extends z.infer<typeof StoragePublicConfig> {
124
+ }
125
+ export declare const StorageConfig: z.ZodObject<{
126
+ batch: z.ZodObject<{
127
+ enabled: z.ZodBoolean;
128
+ max_items: z.ZodInt;
129
+ max_item_size: z.ZodInt;
130
+ }, z.core.$strip>;
131
+ chunk: z.ZodBoolean;
132
+ max_transfer_size: z.ZodInt;
133
+ max_chunks: z.ZodInt;
134
+ app_enabled: z.ZodBoolean;
135
+ cas: z.ZodObject<{
136
+ enabled: z.ZodOptional<z.ZodBoolean>;
137
+ include: z.ZodOptional<z.ZodArray<z.ZodString>>;
138
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
139
+ }, z.core.$strip>;
140
+ data: z.ZodString;
141
+ enabled: z.ZodBoolean;
142
+ limits: z.ZodObject<{
143
+ item_size: z.ZodInt;
144
+ user_items: z.ZodInt;
145
+ user_size: z.ZodInt;
146
+ }, z.core.$strip>;
147
+ trash_duration: z.ZodNumber;
148
+ }, z.core.$strip>;
149
+ declare module '@axium/core/plugins' {
150
+ interface $PluginConfigs {
151
+ '@axium/storage': z.infer<typeof StorageConfig>;
152
+ }
153
+ }
125
154
  declare const StorageAPI: {
126
155
  readonly 'users/:id/storage': {
127
156
  readonly OPTIONS: z.ZodObject<{
128
157
  limits: z.ZodObject<{
129
- item_size: z.ZodNumber;
130
- user_items: z.ZodNumber;
131
- user_size: z.ZodNumber;
158
+ item_size: z.ZodInt;
159
+ user_items: z.ZodInt;
160
+ user_size: z.ZodInt;
132
161
  }, z.core.$strip>;
133
- usedBytes: z.ZodNumber;
134
- itemCount: z.ZodNumber;
162
+ usedBytes: z.ZodInt;
163
+ itemCount: z.ZodInt;
135
164
  lastModified: z.ZodCoercedDate<unknown>;
136
165
  lastTrashed: z.ZodNullable<z.ZodCoercedDate<unknown>>;
137
166
  }, z.core.$strip>;
@@ -152,12 +181,12 @@ declare const StorageAPI: {
152
181
  metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
153
182
  }, z.core.$strip>>;
154
183
  limits: z.ZodObject<{
155
- item_size: z.ZodNumber;
156
- user_items: z.ZodNumber;
157
- user_size: z.ZodNumber;
184
+ item_size: z.ZodInt;
185
+ user_items: z.ZodInt;
186
+ user_size: z.ZodInt;
158
187
  }, z.core.$strip>;
159
- usedBytes: z.ZodNumber;
160
- itemCount: z.ZodNumber;
188
+ usedBytes: z.ZodInt;
189
+ itemCount: z.ZodInt;
161
190
  lastModified: z.ZodCoercedDate<unknown>;
162
191
  lastTrashed: z.ZodNullable<z.ZodCoercedDate<unknown>>;
163
192
  }, z.core.$strip>;
@@ -217,14 +246,14 @@ declare const StorageAPI: {
217
246
  readonly OPTIONS: z.ZodObject<{
218
247
  batch: z.ZodObject<{
219
248
  enabled: z.ZodBoolean;
220
- max_items: z.ZodNumber;
221
- max_item_size: z.ZodNumber;
249
+ max_items: z.ZodInt;
250
+ max_item_size: z.ZodInt;
222
251
  }, z.core.$strip>;
223
252
  chunk: z.ZodBoolean;
224
- max_transfer_size: z.ZodNumber;
225
- max_chunks: z.ZodNumber;
226
- syncProtocolVersion: z.ZodNumber;
227
- batchFormatVersion: z.ZodNumber;
253
+ max_transfer_size: z.ZodInt;
254
+ max_chunks: z.ZodInt;
255
+ syncProtocolVersion: z.ZodInt32;
256
+ batchFormatVersion: z.ZodInt32;
228
257
  }, z.core.$strip>;
229
258
  };
230
259
  readonly 'storage/batch': {
package/dist/common.js CHANGED
@@ -1,22 +1,5 @@
1
- import { $API } from '@axium/core';
1
+ import { $API, setServerConfig } from '@axium/core';
2
2
  import * as z from 'zod';
3
- export const StoragePublicConfig = z.object({
4
- /** Configuration for batch updates */
5
- batch: z.object({
6
- /** Whether to enable sending multiple files per request */
7
- enabled: z.boolean(),
8
- /** Maximum number of items that can be included in a single batch update */
9
- max_items: z.number(),
10
- /** Maximum size in KiB per item */
11
- max_item_size: z.number(),
12
- }),
13
- /** Whether to split files larger than `max_transfer_size` into multiple chunks */
14
- chunk: z.boolean(),
15
- /** Maximum size in MiB per transfer/request */
16
- max_transfer_size: z.number(),
17
- /** Maximum number of chunks */
18
- max_chunks: z.number(),
19
- });
20
3
  /**
21
4
  * An update to file metadata.
22
5
  */
@@ -46,15 +29,15 @@ export const StorageItemMetadata = z.object({
46
29
  export const syncProtocolVersion = 0;
47
30
  export const StorageLimits = z.object({
48
31
  /** The maximum size per item in MB */
49
- item_size: z.number(),
32
+ item_size: z.int().nonnegative(),
50
33
  /** Maximum number of items per user */
51
- user_items: z.number(),
34
+ user_items: z.int().nonnegative(),
52
35
  /** The maximum storage size per user in MB */
53
- user_size: z.number(),
36
+ user_size: z.int().nonnegative(),
54
37
  });
55
38
  export const StorageStats = z.object({
56
- usedBytes: z.number().nonnegative(),
57
- itemCount: z.number().nonnegative(),
39
+ usedBytes: z.int().nonnegative(),
40
+ itemCount: z.int().nonnegative(),
58
41
  lastModified: z.coerce.date(),
59
42
  lastTrashed: z.coerce.date().nullable(),
60
43
  });
@@ -85,6 +68,47 @@ export const StorageBatchUpdate = z.object({
85
68
  metadata: z.record(z.uuid(), StorageItemUpdate),
86
69
  content: z.record(z.uuid(), BatchedContentChange),
87
70
  });
71
+ export const StoragePublicConfig = z.object({
72
+ /** Configuration for batch updates */
73
+ batch: z.object({
74
+ /** Whether to enable sending multiple files per request */
75
+ enabled: z.boolean(),
76
+ /** Maximum number of items that can be included in a single batch update */
77
+ max_items: z.int().positive(),
78
+ /** Maximum size in KiB per item */
79
+ max_item_size: z.int().positive(),
80
+ }),
81
+ /** Whether to split files larger than `max_transfer_size` into multiple chunks */
82
+ chunk: z.boolean(),
83
+ /** Maximum size in MiB per transfer/request */
84
+ max_transfer_size: z.int().positive(),
85
+ /** Maximum number of chunks */
86
+ max_chunks: z.int().positive(),
87
+ });
88
+ export const StorageConfig = StoragePublicConfig.safeExtend({
89
+ /** Whether the files app is enabled. Requires `enabled` */
90
+ app_enabled: z.boolean(),
91
+ /** Content Addressable Storage (CAS) configuration */
92
+ cas: z
93
+ .object({
94
+ /** Whether to use CAS */
95
+ enabled: z.boolean(),
96
+ /** Mime types to include when determining if CAS should be used */
97
+ include: z.string().array(),
98
+ /** Mime types to exclude when determining if CAS should be used */
99
+ exclude: z.string().array(),
100
+ })
101
+ .partial(),
102
+ /** Path to data directory */
103
+ data: z.string(),
104
+ /** Whether the storage API endpoints are enabled */
105
+ enabled: z.boolean(),
106
+ /** Default limits */
107
+ limits: StorageLimits,
108
+ /** How many days files are kept in the trash */
109
+ trash_duration: z.number(),
110
+ });
111
+ setServerConfig('@axium/storage', StorageConfig);
88
112
  const StorageAPI = {
89
113
  'users/:id/storage': {
90
114
  OPTIONS: UserStorageInfo,
@@ -101,8 +125,8 @@ const StorageAPI = {
101
125
  },
102
126
  storage: {
103
127
  OPTIONS: StoragePublicConfig.extend({
104
- syncProtocolVersion: z.number(),
105
- batchFormatVersion: z.number(),
128
+ syncProtocolVersion: z.int32().nonnegative(),
129
+ batchFormatVersion: z.int32().nonnegative(),
106
130
  }),
107
131
  },
108
132
  'storage/batch': {
@@ -1,5 +1,5 @@
1
+ import { getConfig } from '@axium/core';
1
2
  import { checkAuthForItem, checkAuthForUser } from '@axium/server/auth';
2
- import { config } from '@axium/server/config';
3
3
  import { database } from '@axium/server/database';
4
4
  import { error, parseBody, withError } from '@axium/server/requests';
5
5
  import { addRoute } from '@axium/server/routes';
@@ -13,7 +13,7 @@ addRoute({
13
13
  path: '/api/storage',
14
14
  OPTIONS() {
15
15
  return {
16
- ...pick(config.storage, 'batch', 'chunk', 'max_chunks', 'max_transfer_size'),
16
+ ...pick(getConfig('@axium/storage'), 'batch', 'chunk', 'max_chunks', 'max_transfer_size'),
17
17
  syncProtocolVersion,
18
18
  batchFormatVersion,
19
19
  };
@@ -23,13 +23,13 @@ addRoute({
23
23
  path: '/api/storage/item/:id',
24
24
  params: { id: z.uuid() },
25
25
  async GET(request, { id: itemId }) {
26
- if (!config.storage.enabled)
26
+ if (!getConfig('@axium/storage').enabled)
27
27
  error(503, 'User storage is disabled');
28
28
  const { item } = await checkAuthForItem(request, 'storage', itemId, { read: true });
29
29
  return parseItem(item);
30
30
  },
31
31
  async PATCH(request, { id: itemId }) {
32
- if (!config.storage.enabled)
32
+ if (!getConfig('@axium/storage').enabled)
33
33
  error(503, 'User storage is disabled');
34
34
  const body = await parseBody(request, StorageItemUpdate);
35
35
  await checkAuthForItem(request, 'storage', itemId, { manage: true });
@@ -51,7 +51,7 @@ addRoute({
51
51
  .catch(withError('Could not update item')));
52
52
  },
53
53
  async DELETE(request, { id: itemId }) {
54
- if (!config.storage.enabled)
54
+ if (!getConfig('@axium/storage').enabled)
55
55
  error(503, 'User storage is disabled');
56
56
  const auth = await checkAuthForItem(request, 'storage', itemId, { manage: true });
57
57
  const item = parseItem(auth.item);
@@ -63,7 +63,7 @@ addRoute({
63
63
  path: '/api/storage/directory/:id',
64
64
  params: { id: z.uuid() },
65
65
  async GET(request, { id: itemId }) {
66
- if (!config.storage.enabled)
66
+ if (!getConfig('@axium/storage').enabled)
67
67
  error(503, 'User storage is disabled');
68
68
  const { item } = await checkAuthForItem(request, 'storage', itemId, { read: true });
69
69
  if (item.type != 'inode/directory')
@@ -81,7 +81,7 @@ addRoute({
81
81
  path: '/api/storage/directory/:id/recursive',
82
82
  params: { id: z.uuid() },
83
83
  async GET(request, { id: itemId }) {
84
- if (!config.storage.enabled)
84
+ if (!getConfig('@axium/storage').enabled)
85
85
  error(503, 'User storage is disabled');
86
86
  const { item } = await checkAuthForItem(request, 'storage', itemId, { read: true });
87
87
  if (item.type != 'inode/directory')
@@ -94,14 +94,14 @@ addRoute({
94
94
  path: '/api/users/:id/storage',
95
95
  params: { id: z.uuid() },
96
96
  async OPTIONS(request, { id: userId }) {
97
- if (!config.storage.enabled)
97
+ if (!getConfig('@axium/storage').enabled)
98
98
  error(503, 'User storage is disabled');
99
99
  await checkAuthForUser(request, userId);
100
100
  const [stats, limits] = await Promise.all([getUserStats(userId), getLimits(userId)]).catch(withError('Could not fetch data'));
101
101
  return Object.assign(stats, { limits });
102
102
  },
103
103
  async GET(request, { id: userId }) {
104
- if (!config.storage.enabled)
104
+ if (!getConfig('@axium/storage').enabled)
105
105
  error(503, 'User storage is disabled');
106
106
  await checkAuthForUser(request, userId);
107
107
  const [items, stats, limits] = await Promise.all([
@@ -116,7 +116,7 @@ addRoute({
116
116
  path: '/api/users/:id/storage/root',
117
117
  params: { id: z.uuid() },
118
118
  async GET(request, { id: userId }) {
119
- if (!config.storage.enabled)
119
+ if (!getConfig('@axium/storage').enabled)
120
120
  error(503, 'User storage is disabled');
121
121
  await checkAuthForUser(request, userId);
122
122
  const items = await database
@@ -148,7 +148,7 @@ addRoute({
148
148
  path: '/api/users/:id/storage/shared',
149
149
  params: { id: z.uuid() },
150
150
  async GET(request, { id: userId }) {
151
- if (!config.storage.enabled)
151
+ if (!getConfig('@axium/storage').enabled)
152
152
  error(503, 'User storage is disabled');
153
153
  const { user } = await checkAuthForUser(request, userId);
154
154
  const items = await database
@@ -166,7 +166,7 @@ addRoute({
166
166
  path: '/api/users/:id/storage/trash',
167
167
  params: { id: z.uuid() },
168
168
  async GET(request, { id: userId }) {
169
- if (!config.storage.enabled)
169
+ if (!getConfig('@axium/storage').enabled)
170
170
  error(503, 'User storage is disabled');
171
171
  await checkAuthForUser(request, userId);
172
172
  const items = await database
@@ -1,7 +1,7 @@
1
+ import { getConfig } from '@axium/core';
1
2
  import * as acl from '@axium/server/acl';
2
3
  import { audit } from '@axium/server/audit';
3
4
  import { requireSession } from '@axium/server/auth';
4
- import config from '@axium/server/config';
5
5
  import { database } from '@axium/server/database';
6
6
  import { withError } from '@axium/server/requests';
7
7
  import { addRoute } from '@axium/server/routes';
@@ -16,9 +16,9 @@ import { getRecursiveIds, getUserStats, parseItem } from './db.js';
16
16
  addRoute({
17
17
  path: '/api/storage/batch',
18
18
  async POST(req) {
19
- if (!config.storage.enabled)
19
+ if (!getConfig('@axium/storage').enabled)
20
20
  error(503, 'User storage is disabled');
21
- if (!config.storage.batch.enabled)
21
+ if (!getConfig('@axium/storage').batch.enabled)
22
22
  error(503, 'Batch updates are disabled');
23
23
  const { userId, user } = await requireSession(req);
24
24
  const [usage, limits] = await Promise.all([getUserStats(userId), getLimits(userId)]).catch(withError('Could not fetch usage and/or limits'));
@@ -91,14 +91,14 @@ addRoute({
91
91
  .set({ size, modifiedAt: new Date(), hash })
92
92
  .returningAll()
93
93
  .executeTakeFirstOrThrow();
94
- writeFileSync(join(config.storage.data, result.id), content);
94
+ writeFileSync(join(getConfig('@axium/storage').data, result.id), content);
95
95
  await tx.commit().execute();
96
96
  results.set(itemId, parseItem(result));
97
97
  }
98
98
  const toDelete = await Array.fromAsync(getRecursiveIds(...header.deleted)).catch(withError('Could not get items to delete', 500));
99
99
  const deleted = await tx.deleteFrom('storage').where('id', 'in', header.deleted).returningAll().execute();
100
100
  for (const id of toDelete)
101
- unlinkSync(join(config.storage.data, id));
101
+ unlinkSync(join(getConfig('@axium/storage').data, id));
102
102
  for (const item of deleted)
103
103
  results.set(item.id, parseItem(item));
104
104
  for (const [itemId, update] of Object.entries(header.metadata)) {
@@ -1,35 +1,5 @@
1
- import { StorageLimits } from '../common.js';
1
+ import type { StorageLimits } from '../common.js';
2
2
  import '../polyfills.js';
3
- import * as z from 'zod';
4
- declare const StorageConfig: z.ZodObject<{
5
- batch: z.ZodObject<{
6
- enabled: z.ZodBoolean;
7
- max_items: z.ZodNumber;
8
- max_item_size: z.ZodNumber;
9
- }, z.core.$strip>;
10
- chunk: z.ZodBoolean;
11
- max_transfer_size: z.ZodNumber;
12
- max_chunks: z.ZodNumber;
13
- app_enabled: z.ZodBoolean;
14
- cas: z.ZodOptional<z.ZodObject<{
15
- enabled: z.ZodBoolean;
16
- include: z.ZodArray<z.ZodString>;
17
- exclude: z.ZodArray<z.ZodString>;
18
- }, z.core.$strip>>;
19
- data: z.ZodString;
20
- enabled: z.ZodBoolean;
21
- limits: z.ZodObject<{
22
- item_size: z.ZodNumber;
23
- user_items: z.ZodNumber;
24
- user_size: z.ZodNumber;
25
- }, z.core.$strip>;
26
- trash_duration: z.ZodNumber;
27
- }, z.core.$strip>;
28
- declare module '@axium/server/config' {
29
- interface Config {
30
- storage: z.infer<typeof StorageConfig>;
31
- }
32
- }
33
3
  export declare const defaultCASMime: RegExp[];
34
4
  declare module '@axium/server/audit' {
35
5
  interface $EventTypes {
@@ -50,4 +20,3 @@ export type ExternalLimitHandler = (userId?: string) => StorageLimits | Promise<
50
20
  */
51
21
  export declare function useLimits(handler: ExternalLimitHandler): void;
52
22
  export declare function getLimits(userId?: string): Promise<StorageLimits>;
53
- export {};
@@ -1,62 +1,8 @@
1
- import { Severity } from '@axium/core';
1
+ import { getConfig, Severity } from '@axium/core';
2
2
  import { addEvent } from '@axium/server/audit';
3
- import { addConfig, addConfigDefaults, config } from '@axium/server/config';
4
- import { StorageLimits, StoragePublicConfig } from '../common.js';
5
- import '../polyfills.js';
6
3
  import * as z from 'zod';
7
- const StorageConfig = StoragePublicConfig.safeExtend({
8
- /** Whether the files app is enabled. Requires `enabled` */
9
- app_enabled: z.boolean(),
10
- /** Content Addressable Storage (CAS) configuration */
11
- cas: z
12
- .object({
13
- /** Whether to use CAS */
14
- enabled: z.boolean(),
15
- /** Mime types to include when determining if CAS should be used */
16
- include: z.string().array(),
17
- /** Mime types to exclude when determining if CAS should be used */
18
- exclude: z.string().array(),
19
- })
20
- .optional(),
21
- /** Path to data directory */
22
- data: z.string(),
23
- /** Whether the storage API endpoints are enabled */
24
- enabled: z.boolean(),
25
- /** Default limits */
26
- limits: StorageLimits,
27
- /** How many days files are kept in the trash */
28
- trash_duration: z.number(),
29
- });
30
- addConfig({
31
- storage: StorageConfig.optional(),
32
- });
4
+ import '../polyfills.js';
33
5
  export const defaultCASMime = [/video\/.*/, /audio\/.*/];
34
- addConfigDefaults({
35
- storage: {
36
- app_enabled: true,
37
- batch: {
38
- enabled: false,
39
- max_items: 100,
40
- max_item_size: 100,
41
- },
42
- cas: {
43
- enabled: true,
44
- include: [],
45
- exclude: [],
46
- },
47
- chunk: false,
48
- data: '/srv/axium/storage',
49
- enabled: true,
50
- limits: {
51
- user_size: 1000,
52
- item_size: 100,
53
- user_items: 10_000,
54
- },
55
- max_chunks: 10,
56
- max_transfer_size: 100,
57
- trash_duration: 30,
58
- },
59
- });
60
6
  addEvent({
61
7
  source: '@axium/storage',
62
8
  name: 'storage_type_mismatch',
@@ -83,6 +29,6 @@ export async function getLimits(userId) {
83
29
  return await _getLimits(userId);
84
30
  }
85
31
  catch {
86
- return config.storage.limits;
32
+ return getConfig('@axium/storage').limits;
87
33
  }
88
34
  }
package/dist/server/db.js CHANGED
@@ -1,4 +1,4 @@
1
- import { config } from '@axium/server/config';
1
+ import { getConfig } from '@axium/core';
2
2
  import { database } from '@axium/server/database';
3
3
  import { withError } from '@axium/server/requests';
4
4
  import { unlinkSync } from 'node:fs';
@@ -62,5 +62,5 @@ export async function deleteRecursive(deleteSelf, ...itemId) {
62
62
  toDelete.push(...itemId);
63
63
  await database.deleteFrom('storage').where('id', '=', itemId).returningAll().execute().catch(withError('Could not delete item'));
64
64
  for (const id of toDelete)
65
- unlinkSync(join(config.storage.data, id));
65
+ unlinkSync(join(getConfig('@axium/storage').data, id));
66
66
  }
@@ -1,5 +1,6 @@
1
1
  import type { OpOptions } from '@axium/server/database';
2
2
  import '../common.js';
3
3
  import './index.js';
4
+ export declare function load(): void;
4
5
  export declare function statusText(): Promise<string>;
5
6
  export declare function clean(opt: OpOptions): Promise<void>;
@@ -1,11 +1,13 @@
1
+ import { getConfig } from '@axium/core';
1
2
  import { formatBytes } from '@axium/core/format';
2
3
  import { done, start } from '@axium/core/node/io';
3
- import config from '@axium/server/config';
4
4
  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
- mkdirSync(config.storage.data, { recursive: true });
8
+ export function load() {
9
+ mkdirSync(getConfig('@axium/storage').data, { recursive: true });
10
+ }
9
11
  export async function statusText() {
10
12
  const { storage: items } = await count('storage');
11
13
  const { size } = await database
@@ -16,7 +18,7 @@ export async function statusText() {
16
18
  }
17
19
  export async function clean(opt) {
18
20
  start('Removing expired trash items');
19
- const nDaysAgo = new Date(Date.now() - 86400000 * config.storage.trash_duration);
21
+ const nDaysAgo = new Date(Date.now() - 86400000 * getConfig('@axium/storage').trash_duration);
20
22
  await database
21
23
  .deleteFrom('storage')
22
24
  .where('trashedAt', 'is not', null)
@@ -1,6 +1,6 @@
1
+ import { getConfig } from '@axium/core';
1
2
  import { audit } from '@axium/server/audit';
2
3
  import { checkAuthForItem, requireSession } from '@axium/server/auth';
3
- import { config } from '@axium/server/config';
4
4
  import { database } from '@axium/server/database';
5
5
  import { error, withError } from '@axium/server/requests';
6
6
  import { addRoute } from '@axium/server/routes';
@@ -14,7 +14,7 @@ import { getUserStats, parseItem } from './db.js';
14
14
  addRoute({
15
15
  path: '/raw/storage',
16
16
  async PUT(request) {
17
- if (!config.storage.enabled)
17
+ if (!getConfig('@axium/storage').enabled)
18
18
  error(503, 'User storage is disabled');
19
19
  const { userId } = await requireSession(request);
20
20
  const [usage, limits] = await Promise.all([getUserStats(userId), getLimits(userId)]).catch(withError('Could not fetch usage and/or limits'));
@@ -50,9 +50,9 @@ addRoute({
50
50
  const isDirectory = type == 'inode/directory';
51
51
  if (isDirectory && size > 0)
52
52
  error(400, 'Directories can not have content');
53
- const useCAS = config.storage.cas.enabled &&
53
+ const useCAS = getConfig('@axium/storage').cas.enabled &&
54
54
  !isDirectory &&
55
- (defaultCASMime.some(pattern => pattern.test(type)) || config.storage.cas.include.some(mime => type.match(mime)));
55
+ (defaultCASMime.some(pattern => pattern.test(type)) || getConfig('@axium/storage').cas.include?.some(mime => type.match(mime)));
56
56
  const hash = isDirectory ? null : createHash('BLAKE2b512').update(content).digest();
57
57
  const tx = await database.startTransaction().execute();
58
58
  try {
@@ -61,7 +61,7 @@ addRoute({
61
61
  .values({ userId, hash, name, size, type, immutable: useCAS, parentId })
62
62
  .returningAll()
63
63
  .executeTakeFirstOrThrow());
64
- const path = join(config.storage.data, item.id);
64
+ const path = join(getConfig('@axium/storage').data, item.id);
65
65
  if (!useCAS) {
66
66
  if (!isDirectory)
67
67
  writeFileSync(path, content);
@@ -81,7 +81,7 @@ addRoute({
81
81
  await tx.commit().execute();
82
82
  return item;
83
83
  }
84
- linkSync(join(config.storage.data, existing.id), path);
84
+ linkSync(join(getConfig('@axium/storage').data, existing.id), path);
85
85
  await tx.commit().execute();
86
86
  return item;
87
87
  }
@@ -95,12 +95,12 @@ addRoute({
95
95
  path: '/raw/storage/:id',
96
96
  params: { id: z.uuid() },
97
97
  async GET(request, { id: itemId }) {
98
- if (!config.storage.enabled)
98
+ if (!getConfig('@axium/storage').enabled)
99
99
  error(503, 'User storage is disabled');
100
100
  const { item } = await checkAuthForItem(request, 'storage', itemId, { read: true });
101
101
  if (item.trashedAt)
102
102
  error(410, 'Trashed items can not be downloaded');
103
- const content = new Uint8Array(readFileSync(join(config.storage.data, item.id)));
103
+ const content = new Uint8Array(readFileSync(join(getConfig('@axium/storage').data, item.id)));
104
104
  return new Response(content, {
105
105
  headers: {
106
106
  'Content-Type': item.type,
@@ -109,7 +109,7 @@ addRoute({
109
109
  });
110
110
  },
111
111
  async POST(request, { id: itemId }) {
112
- if (!config.storage.enabled)
112
+ if (!getConfig('@axium/storage').enabled)
113
113
  error(503, 'User storage is disabled');
114
114
  const { item, session } = await checkAuthForItem(request, 'storage', itemId, { write: true });
115
115
  if (item.immutable)
@@ -145,7 +145,7 @@ addRoute({
145
145
  .set({ size, modifiedAt: new Date(), hash })
146
146
  .returningAll()
147
147
  .executeTakeFirstOrThrow();
148
- writeFileSync(join(config.storage.data, result.id), content);
148
+ writeFileSync(join(getConfig('@axium/storage').data, result.id), content);
149
149
  await tx.commit().execute();
150
150
  return parseItem(result);
151
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/storage",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "description": "User file storage for Axium",
6
6
  "funding": {
@@ -39,8 +39,8 @@
39
39
  "build": "tsc"
40
40
  },
41
41
  "peerDependencies": {
42
- "@axium/client": ">=0.11.0",
43
- "@axium/core": ">=0.17.0",
42
+ "@axium/client": ">=0.12.0",
43
+ "@axium/core": ">=0.18.0",
44
44
  "@axium/server": ">=0.30.0",
45
45
  "@sveltejs/kit": "^2.27.3",
46
46
  "utilium": "^2.3.8"
@@ -54,7 +54,8 @@
54
54
  "hooks": "./dist/server/hooks.js",
55
55
  "routes": "./routes",
56
56
  "cli": "./dist/server/cli.js",
57
- "db": "./db.json"
57
+ "db": "./db.json",
58
+ "web_client_hooks": "./dist/common.js"
58
59
  },
59
60
  "client": {
60
61
  "cli": "./dist/client/cli.js",
@@ -67,6 +68,30 @@
67
68
  "icon": "folders"
68
69
  }
69
70
  ],
70
- "update_checks": true
71
+ "update_checks": true,
72
+ "config": {
73
+ "app_enabled": true,
74
+ "batch": {
75
+ "enabled": false,
76
+ "max_items": 100,
77
+ "max_item_size": 100
78
+ },
79
+ "cas": {
80
+ "enabled": true,
81
+ "include": [],
82
+ "exclude": []
83
+ },
84
+ "chunk": false,
85
+ "data": "/srv/axium/storage",
86
+ "enabled": true,
87
+ "limits": {
88
+ "user_size": 1000,
89
+ "item_size": 100,
90
+ "user_items": 10000
91
+ },
92
+ "max_chunks": 10,
93
+ "max_transfer_size": 100,
94
+ "trash_duration": 30
95
+ }
71
96
  }
72
97
  }