@axium/storage 0.20.1 → 0.20.3

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,55 +1,3 @@
1
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
- if (value !== null && value !== void 0) {
3
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
- var dispose, inner;
5
- if (async) {
6
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
- dispose = value[Symbol.asyncDispose];
8
- }
9
- if (dispose === void 0) {
10
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
- dispose = value[Symbol.dispose];
12
- if (async) inner = dispose;
13
- }
14
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
- env.stack.push({ value: value, dispose: dispose, async: async });
17
- }
18
- else if (async) {
19
- env.stack.push({ async: true });
20
- }
21
- return value;
22
- };
23
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
- return function (env) {
25
- function fail(e) {
26
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
- env.hasError = true;
28
- }
29
- var r, s = 0;
30
- function next() {
31
- while (r = env.stack.pop()) {
32
- try {
33
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
- if (r.dispose) {
35
- var result = r.dispose.call(r.value);
36
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
- }
38
- else s |= 1;
39
- }
40
- catch (e) {
41
- fail(e);
42
- }
43
- }
44
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
- if (env.hasError) throw env.error;
46
- }
47
- return next();
48
- };
49
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
- var e = new Error(message);
51
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
- });
53
1
  import { getConfig } from '@axium/core';
54
2
  import { audit } from '@axium/server/audit';
55
3
  import { authRequestForItem, requireSession } from '@axium/server/auth';
@@ -57,8 +5,9 @@ import { database } from '@axium/server/database';
57
5
  import { error, withError } from '@axium/server/requests';
58
6
  import { addRoute } from '@axium/server/routes';
59
7
  import { createHash } from 'node:crypto';
60
- import { closeSync, copyFileSync, openSync, readSync, renameSync, unlinkSync, writeFileSync, writeSync } from 'node:fs';
8
+ import { copyFileSync, createReadStream, renameSync, unlinkSync, writeFileSync, writeSync } from 'node:fs';
61
9
  import { join } from 'node:path/posix';
10
+ import { Readable } from 'node:stream';
62
11
  import * as z from 'zod';
63
12
  import '../polyfills.js';
64
13
  import { getLimits } from './config.js';
@@ -147,53 +96,40 @@ addRoute({
147
96
  path: '/raw/storage/:id',
148
97
  params: { id: z.uuid() },
149
98
  async GET(request, { id: itemId }) {
150
- const env_1 = { stack: [], error: void 0, hasError: false };
151
- try {
152
- if (!getConfig('@axium/storage').enabled)
153
- error(503, 'User storage is disabled');
154
- const { item } = await authRequestForItem(request, 'storage', itemId, { read: true }, true);
155
- if (item.trashedAt)
156
- error(410, 'Trashed items can not be downloaded');
157
- const path = join(getConfig('@axium/storage').data, item.id);
158
- const range = request.headers.get('range');
159
- const fd = openSync(path, 'r');
160
- const _ = __addDisposableResource(env_1, { [Symbol.dispose]: () => closeSync(fd) }, false);
161
- let start = 0, end = Number(item.size - 1n), length = Number(item.size);
162
- if (range) {
163
- const [_start, _end = end] = range
164
- .replace(/bytes=/, '')
165
- .split('-')
166
- .map(val => (val && Number.isSafeInteger(parseInt(val)) ? parseInt(val) : undefined));
167
- start = typeof _start == 'number' ? _start : Number(item.size) - _end;
168
- end = typeof _start == 'number' ? _end : end;
169
- length = end - start + 1;
170
- }
171
- if (start >= item.size || end >= item.size || start > end || start < 0) {
172
- return new Response(null, {
173
- status: 416,
174
- headers: { 'Content-Range': `bytes */${item.size}` },
175
- });
176
- }
177
- const content = new Uint8Array(length);
178
- readSync(fd, content, 0, length, start);
179
- return new Response(content, {
180
- status: BigInt(length) == item.size ? 200 : 206,
181
- headers: {
182
- 'Content-Range': `bytes ${start}-${end}/${item.size}`,
183
- 'Accept-Ranges': 'bytes',
184
- 'Content-Length': String(length),
185
- 'Content-Type': item.type,
186
- 'Content-Disposition': contentDispositionFor(item.name),
187
- },
188
- });
189
- }
190
- catch (e_1) {
191
- env_1.error = e_1;
192
- env_1.hasError = true;
99
+ if (!getConfig('@axium/storage').enabled)
100
+ error(503, 'User storage is disabled');
101
+ const { item } = await authRequestForItem(request, 'storage', itemId, { read: true }, true);
102
+ if (item.trashedAt)
103
+ error(410, 'Trashed items can not be downloaded');
104
+ const path = join(getConfig('@axium/storage').data, item.id);
105
+ const range = request.headers.get('range');
106
+ let start = 0, end = Number(item.size - 1n), length = Number(item.size);
107
+ if (range) {
108
+ const [_start, _end = end] = range
109
+ .replace(/bytes=/, '')
110
+ .split('-')
111
+ .map(val => (val && Number.isSafeInteger(parseInt(val)) ? parseInt(val) : undefined));
112
+ start = typeof _start == 'number' ? _start : Number(item.size) - _end;
113
+ end = typeof _start == 'number' ? _end : end;
114
+ length = end - start + 1;
193
115
  }
194
- finally {
195
- __disposeResources(env_1);
116
+ if (start >= item.size || end >= item.size || start > end || start < 0) {
117
+ return new Response(null, {
118
+ status: 416,
119
+ headers: { 'Content-Range': `bytes */${item.size}` },
120
+ });
196
121
  }
122
+ const content = Readable.toWeb(createReadStream(path, { start, end }));
123
+ return new Response(content, {
124
+ status: BigInt(length) == item.size ? 200 : 206,
125
+ headers: {
126
+ 'Content-Range': `bytes ${start}-${end}/${item.size}`,
127
+ 'Accept-Ranges': 'bytes',
128
+ 'Content-Length': String(length),
129
+ 'Content-Type': item.type,
130
+ 'Content-Disposition': contentDispositionFor(item.name),
131
+ },
132
+ });
197
133
  },
198
134
  async POST(request, { id: itemId }) {
199
135
  if (!getConfig('@axium/storage').enabled)
@@ -0,0 +1,110 @@
1
+ :host {
2
+ anchor-scope: --preview-openers;
3
+ }
4
+
5
+ .preview-action {
6
+ --size: 18px;
7
+ }
8
+
9
+ .preview-action:hover {
10
+ cursor: pointer;
11
+ }
12
+
13
+ .preview-top-bar {
14
+ display: flex;
15
+ align-items: center;
16
+ gap: 1em;
17
+ justify-content: space-between;
18
+ padding: 0;
19
+ position: absolute;
20
+ inset: 0.5em 1em 0;
21
+ height: fit-content;
22
+
23
+ > div {
24
+ display: flex;
25
+ gap: 1em;
26
+ align-items: center;
27
+ }
28
+ }
29
+
30
+ .openers {
31
+ padding: 1em;
32
+ border: var(--border-accent);
33
+ border-radius: 1em;
34
+ height: 2em;
35
+ anchor-name: --preview-openers;
36
+ }
37
+
38
+ .openers :global([popover]) {
39
+ inset: anchor(bottom) anchor(right) auto anchor(left);
40
+ position-anchor: --preview-openers;
41
+ width: anchor-size(width);
42
+ }
43
+
44
+ .actions {
45
+ right: 0;
46
+ }
47
+
48
+ .preview-content {
49
+ position: absolute;
50
+ inset: 3em 10em 1em;
51
+ display: flex;
52
+ text-align: center;
53
+ align-items: center;
54
+ justify-content: center;
55
+ flex-direction: column;
56
+
57
+ .full-fill {
58
+ position: absolute;
59
+ inset: 0;
60
+ width: 100%;
61
+ height: 100%;
62
+ }
63
+
64
+ .preview-text {
65
+ white-space: pre-wrap;
66
+ overflow-y: scroll;
67
+ line-height: 1.6;
68
+ background-color: var(--bg-menu);
69
+ font-family: monospace;
70
+ }
71
+
72
+ img,
73
+ video {
74
+ max-width: 100%;
75
+ max-height: 100%;
76
+ }
77
+ }
78
+
79
+ .no-preview {
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 1em;
83
+ align-items: center;
84
+ justify-content: center;
85
+ }
86
+
87
+ @media (width < 700px) {
88
+ .preview-top-bar {
89
+ flex-direction: column;
90
+
91
+ .actions {
92
+ justify-content: space-around;
93
+ width: 100%;
94
+
95
+ .preview-action {
96
+ padding: 1em;
97
+ flex: 1 1 0;
98
+ border-radius: 1em;
99
+ border: var(--border-accent);
100
+ padding: 1em;
101
+ justify-content: center;
102
+ display: flex;
103
+ }
104
+ }
105
+ }
106
+
107
+ .preview-content {
108
+ inset: 10em 1em 0;
109
+ }
110
+ }
@@ -7,6 +7,7 @@
7
7
  import { copyShortURL } from '@axium/storage/client/frontend';
8
8
  import type { StorageItemMetadata } from '@axium/storage/common';
9
9
  import '@axium/storage/polyfills';
10
+ import './Preview.css';
10
11
 
11
12
  const {
12
13
  item,
@@ -144,116 +145,3 @@
144
145
  >
145
146
  <p>{text('storage.Preview.download_confirm')}</p>
146
147
  </FormDialog>
147
-
148
- <style>
149
- :host {
150
- anchor-scope: --preview-openers;
151
- }
152
-
153
- .preview-action {
154
- --size: 18px;
155
- }
156
-
157
- .preview-action:hover {
158
- cursor: pointer;
159
- }
160
-
161
- .preview-top-bar {
162
- display: flex;
163
- align-items: center;
164
- gap: 1em;
165
- justify-content: space-between;
166
- padding: 0;
167
- position: absolute;
168
- inset: 0.5em 1em 0;
169
- height: fit-content;
170
-
171
- > div {
172
- display: flex;
173
- gap: 1em;
174
- align-items: center;
175
- }
176
- }
177
-
178
- .openers {
179
- padding: 1em;
180
- border: var(--border-accent);
181
- border-radius: 1em;
182
- height: 2em;
183
- anchor-name: --preview-openers;
184
- }
185
-
186
- .openers :global([popover]) {
187
- inset: anchor(bottom) anchor(right) auto anchor(left);
188
- position-anchor: --preview-openers;
189
- width: anchor-size(width);
190
- }
191
-
192
- .actions {
193
- right: 0;
194
- }
195
-
196
- .preview-content {
197
- position: absolute;
198
- inset: 3em 10em 1em;
199
- display: flex;
200
- text-align: center;
201
- align-items: center;
202
- justify-content: center;
203
- flex-direction: column;
204
-
205
- .full-fill {
206
- position: absolute;
207
- inset: 0;
208
- width: 100%;
209
- height: 100%;
210
- }
211
-
212
- .preview-text {
213
- white-space: pre-wrap;
214
- overflow-y: scroll;
215
- line-height: 1.6;
216
- background-color: var(--bg-menu);
217
- font-family: monospace;
218
- }
219
-
220
- img,
221
- video {
222
- max-width: 100%;
223
- max-height: 100%;
224
- }
225
- }
226
-
227
- .no-preview {
228
- display: flex;
229
- flex-direction: column;
230
- gap: 1em;
231
- align-items: center;
232
- justify-content: center;
233
- }
234
-
235
- @media (width < 700px) {
236
- .preview-top-bar {
237
- flex-direction: column;
238
-
239
- .actions {
240
- justify-content: space-around;
241
- width: 100%;
242
-
243
- .preview-action {
244
- padding: 1em;
245
- flex: 1 1 0;
246
- border-radius: 1em;
247
- border: var(--border-accent);
248
- padding: 1em;
249
- justify-content: center;
250
- display: flex;
251
- }
252
- }
253
- }
254
-
255
- .preview-content {
256
- inset: 10em 1em 0;
257
- }
258
- }
259
- </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/storage",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "description": "User file storage for Axium",
6
6
  "funding": {