ras-stack 0.1.0

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.
Files changed (52) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +148 -0
  3. package/config/oxlint.json +19 -0
  4. package/config/typescript/browser.json +15 -0
  5. package/config/typescript/library.json +13 -0
  6. package/config/typescript/tanstack.json +6 -0
  7. package/dist/auth/index.d.ts +5 -0
  8. package/dist/auth/index.js +6 -0
  9. package/dist/auth/index.js.map +1 -0
  10. package/dist/auth/origins.d.ts +11 -0
  11. package/dist/auth/origins.js +35 -0
  12. package/dist/auth/origins.js.map +1 -0
  13. package/dist/auth/providers.d.ts +6 -0
  14. package/dist/auth/providers.js +13 -0
  15. package/dist/auth/providers.js.map +1 -0
  16. package/dist/auth/random.d.ts +2 -0
  17. package/dist/auth/random.js +10 -0
  18. package/dist/auth/random.js.map +1 -0
  19. package/dist/auth/secret.d.ts +8 -0
  20. package/dist/auth/secret.js +45 -0
  21. package/dist/auth/secret.js.map +1 -0
  22. package/dist/auth/settings.d.ts +28 -0
  23. package/dist/auth/settings.js +18 -0
  24. package/dist/auth/settings.js.map +1 -0
  25. package/dist/email/index.d.ts +30 -0
  26. package/dist/email/index.js +44 -0
  27. package/dist/email/index.js.map +1 -0
  28. package/dist/realtime/index.d.ts +2 -0
  29. package/dist/realtime/index.js +3 -0
  30. package/dist/realtime/index.js.map +1 -0
  31. package/dist/realtime/publisher.d.ts +34 -0
  32. package/dist/realtime/publisher.js +176 -0
  33. package/dist/realtime/publisher.js.map +1 -0
  34. package/dist/realtime/tokens.d.ts +6 -0
  35. package/dist/realtime/tokens.js +13 -0
  36. package/dist/realtime/tokens.js.map +1 -0
  37. package/dist/server/canonical-host.d.ts +5 -0
  38. package/dist/server/canonical-host.js +15 -0
  39. package/dist/server/canonical-host.js.map +1 -0
  40. package/dist/server/health.d.ts +4 -0
  41. package/dist/server/health.js +10 -0
  42. package/dist/server/health.js.map +1 -0
  43. package/dist/server/index.d.ts +3 -0
  44. package/dist/server/index.js +4 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/dist/server/rpc.d.ts +13 -0
  47. package/dist/server/rpc.js +32 -0
  48. package/dist/server/rpc.js.map +1 -0
  49. package/dist/uploads/index.d.ts +30 -0
  50. package/dist/uploads/index.js +77 -0
  51. package/dist/uploads/index.js.map +1 -0
  52. package/package.json +91 -0
@@ -0,0 +1,176 @@
1
+ export class CentrifugoPublisher {
2
+ options;
3
+ pending = new Map();
4
+ queue = [];
5
+ idleWaiters = new Set();
6
+ request;
7
+ maxConcurrentChannels;
8
+ maxPendingChannels;
9
+ active = 0;
10
+ closed = false;
11
+ constructor(options) {
12
+ this.options = options;
13
+ this.request = options.fetch ?? fetch;
14
+ this.maxConcurrentChannels = positiveInteger(options.maxConcurrentChannels ?? 8, 'maxConcurrentChannels');
15
+ this.maxPendingChannels = positiveInteger(options.maxPendingChannels ?? 1_024, 'maxPendingChannels');
16
+ }
17
+ publish(channel, data) {
18
+ if (!this.options.apiUrl)
19
+ return false;
20
+ if (this.closed) {
21
+ this.reportError(new Error('Realtime publisher is closed'), channel);
22
+ return false;
23
+ }
24
+ const pending = this.pending.get(channel);
25
+ if (pending) {
26
+ pending.dirty = true;
27
+ pending.data = data;
28
+ return true;
29
+ }
30
+ if (this.pending.size >= this.maxPendingChannels) {
31
+ this.reportError(new Error('Realtime publisher queue is full'), channel);
32
+ return false;
33
+ }
34
+ const state = { dirty: true, data, running: false };
35
+ this.pending.set(channel, state);
36
+ this.queue.push(channel);
37
+ this.pump();
38
+ return true;
39
+ }
40
+ idle() {
41
+ if (this.isIdle())
42
+ return Promise.resolve();
43
+ return new Promise((resolve) => this.idleWaiters.add(resolve));
44
+ }
45
+ async close() {
46
+ this.closed = true;
47
+ await this.idle();
48
+ }
49
+ pump() {
50
+ while (this.active < this.maxConcurrentChannels) {
51
+ const channel = this.queue.shift();
52
+ if (!channel)
53
+ break;
54
+ const state = this.pending.get(channel);
55
+ if (!state || state.running)
56
+ continue;
57
+ state.running = true;
58
+ this.active++;
59
+ void this.flush(channel, state).finally(() => {
60
+ this.active--;
61
+ this.pump();
62
+ this.resolveIdle();
63
+ });
64
+ }
65
+ }
66
+ async flush(channel, state) {
67
+ let failure;
68
+ try {
69
+ while (state.dirty) {
70
+ state.dirty = false;
71
+ // Publications for one channel must preserve mutation order.
72
+ // oxlint-disable-next-line no-await-in-loop
73
+ await this.deliver(channel, state.data);
74
+ }
75
+ }
76
+ catch (error) {
77
+ failure = error;
78
+ }
79
+ finally {
80
+ if (this.pending.get(channel) === state)
81
+ this.pending.delete(channel);
82
+ }
83
+ if (failure) {
84
+ if (state.dirty) {
85
+ this.pending.set(channel, { dirty: true, data: state.data, running: false });
86
+ this.queue.push(channel);
87
+ this.pump();
88
+ }
89
+ this.reportError(failure, channel);
90
+ }
91
+ }
92
+ async deliver(channel, data) {
93
+ const maxRetries = this.options.maxRetries ?? 3;
94
+ for (let retries = 0;; retries++) {
95
+ try {
96
+ // Retrying must finish before a later publication can overtake this one.
97
+ // oxlint-disable-next-line no-await-in-loop
98
+ await this.deliverOnce(channel, data);
99
+ return;
100
+ }
101
+ catch (error) {
102
+ if (!(error instanceof TransientPublishError))
103
+ throw error;
104
+ if (retries >= maxRetries)
105
+ throw error;
106
+ this.options.onRetry?.(error, channel);
107
+ // oxlint-disable-next-line no-await-in-loop
108
+ await new Promise((resolve) => setTimeout(resolve, this.options.retryMs ?? 1_000));
109
+ }
110
+ }
111
+ }
112
+ async deliverOnce(channel, data) {
113
+ let response;
114
+ try {
115
+ response = await this.request(`${this.options.apiUrl.replace(/\/$/, '')}/publish`, {
116
+ method: 'POST',
117
+ headers: { 'Content-Type': 'application/json', 'X-API-Key': this.options.apiKey },
118
+ body: JSON.stringify({ channel, data }),
119
+ signal: AbortSignal.timeout(this.options.timeoutMs ?? 5_000),
120
+ });
121
+ }
122
+ catch (error) {
123
+ if (error instanceof TypeError || isTimeout(error))
124
+ throw new TransientPublishError('Realtime publish request failed', { cause: error });
125
+ throw error;
126
+ }
127
+ if (!response.ok) {
128
+ const message = `Realtime publish failed with status ${response.status}`;
129
+ if (response.status >= 500 || response.status === 429)
130
+ throw new TransientPublishError(message);
131
+ throw new Error(message);
132
+ }
133
+ const result = await response.json();
134
+ const error = centrifugoError(result);
135
+ if (!error)
136
+ return;
137
+ const message = `Realtime publish failed: ${error.message ?? `code ${error.code ?? 'unknown'}`}`;
138
+ if (error.code === 100)
139
+ throw new TransientPublishError(message);
140
+ throw new Error(message);
141
+ }
142
+ reportError(error, channel) {
143
+ try {
144
+ this.options.onError(error, channel);
145
+ }
146
+ catch { }
147
+ }
148
+ isIdle() {
149
+ return this.pending.size === 0 && this.active === 0 && this.queue.length === 0;
150
+ }
151
+ resolveIdle() {
152
+ if (!this.isIdle())
153
+ return;
154
+ for (const resolve of this.idleWaiters)
155
+ resolve();
156
+ this.idleWaiters.clear();
157
+ }
158
+ }
159
+ class TransientPublishError extends Error {
160
+ }
161
+ function isTimeout(error) {
162
+ return error instanceof DOMException && error.name === 'TimeoutError';
163
+ }
164
+ function centrifugoError(result) {
165
+ if (!result || typeof result !== 'object' || !('error' in result) || !result.error || typeof result.error !== 'object')
166
+ return undefined;
167
+ const code = 'code' in result.error && typeof result.error.code === 'number' ? result.error.code : undefined;
168
+ const message = 'message' in result.error && typeof result.error.message === 'string' ? result.error.message : undefined;
169
+ return { ...(code === undefined ? {} : { code }), ...(message === undefined ? {} : { message }) };
170
+ }
171
+ function positiveInteger(value, name) {
172
+ if (!Number.isSafeInteger(value) || value < 1)
173
+ throw new RangeError(`${name} must be a positive integer`);
174
+ return value;
175
+ }
176
+ //# sourceMappingURL=publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publisher.js","sourceRoot":"","sources":["../../src/realtime/publisher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type RealtimeTokenOptions = {
2
+ secret: string;
3
+ now?: number;
4
+ ttlSeconds?: number;
5
+ };
6
+ export declare function signRealtimeToken(subject: string, claims: Record<string, unknown>, options: RealtimeTokenOptions): string;
@@ -0,0 +1,13 @@
1
+ import crypto from 'node:crypto';
2
+ export function signRealtimeToken(subject, claims, options) {
3
+ const now = options.now ?? Math.floor(Date.now() / 1000);
4
+ return sign({ ...claims, sub: subject, exp: now + (options.ttlSeconds ?? 5 * 60) }, options.secret);
5
+ }
6
+ function sign(payload, secret) {
7
+ const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
8
+ const claims = Buffer.from(JSON.stringify(payload)).toString('base64url');
9
+ const unsigned = `${header}.${claims}`;
10
+ const signature = crypto.createHmac('sha256', secret).update(unsigned).digest('base64url');
11
+ return `${unsigned}.${signature}`;
12
+ }
13
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/realtime/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAQhC,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAA+B,EAAE,OAA6B;IAC/G,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACxD,OAAO,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;AACrG,CAAC;AAED,SAAS,IAAI,CAAC,OAAgC,EAAE,MAAc;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC9F,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IACzE,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAA;IACtC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC1F,OAAO,GAAG,QAAQ,IAAI,SAAS,EAAE,CAAA;AACnC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type CanonicalRedirectOptions = {
2
+ canonicalUrl?: string;
3
+ pathsServedOnAnyHost?: ReadonlySet<string>;
4
+ };
5
+ export declare function canonicalRedirect(requestUrl: string, options: CanonicalRedirectOptions): string | null;
@@ -0,0 +1,15 @@
1
+ export function canonicalRedirect(requestUrl, options) {
2
+ if (!options.canonicalUrl?.trim())
3
+ return null;
4
+ try {
5
+ const canonical = new URL(options.canonicalUrl);
6
+ const incoming = new URL(requestUrl);
7
+ if (incoming.host === canonical.host || options.pathsServedOnAnyHost?.has(incoming.pathname))
8
+ return null;
9
+ return new URL(incoming.pathname + incoming.search + incoming.hash, canonical.origin).toString();
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ //# sourceMappingURL=canonical-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-host.js","sourceRoot":"","sources":["../../src/server/canonical-host.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,OAAiC;IACrF,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE;QAAE,OAAO,IAAI,CAAA;IAC9C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAA;QACpC,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QACzG,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;IAClG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type HealthResponseOptions = {
2
+ errorMessage?: (error: unknown) => string;
3
+ };
4
+ export declare function healthResponse(check: () => Promise<void> | void, options?: HealthResponseOptions): Promise<Response>;
@@ -0,0 +1,10 @@
1
+ export async function healthResponse(check, options = {}) {
2
+ try {
3
+ await check();
4
+ return Response.json({ ok: true });
5
+ }
6
+ catch (error) {
7
+ return Response.json({ ok: false, error: options.errorMessage?.(error) ?? 'health check failed' }, { status: 503 });
8
+ }
9
+ }
10
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/server/health.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAiC,EAAE,OAAO,GAA0B,EAAE;IACzG,IAAI,CAAC;QACH,MAAM,KAAK,EAAE,CAAA;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,IAAI,qBAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IACrH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './canonical-host.js';
2
+ export * from './health.js';
3
+ export * from './rpc.js';
@@ -0,0 +1,4 @@
1
+ export * from './canonical-host.js';
2
+ export * from './health.js';
3
+ export * from './rpc.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA"}
@@ -0,0 +1,13 @@
1
+ export type RpcLogger = (error: unknown, context: {
2
+ method?: string;
3
+ path?: string;
4
+ }) => void;
5
+ export type RpcOptions = {
6
+ getRequest?: () => Request;
7
+ requireMutation?: (request: Request) => void;
8
+ logError?: RpcLogger;
9
+ };
10
+ export declare function createRpc(options?: RpcOptions): {
11
+ rpc: <T>(work: () => Promise<T> | T) => Promise<T>;
12
+ mutationRpc: <T>(work: () => Promise<T> | T, request?: Request | undefined) => Promise<T>;
13
+ };
@@ -0,0 +1,32 @@
1
+ export function createRpc(options = {}) {
2
+ async function rpc(work) {
3
+ try {
4
+ return await work();
5
+ }
6
+ catch (error) {
7
+ if (error instanceof Response)
8
+ throw new Error((await error.text()) || `request failed (${error.status})`, { cause: error });
9
+ options.logError?.(error, requestContext(options.getRequest));
10
+ throw error;
11
+ }
12
+ }
13
+ function mutationRpc(work, request = options.getRequest?.()) {
14
+ return rpc(() => {
15
+ if (!request)
16
+ throw new Error('mutation request is unavailable');
17
+ options.requireMutation?.(request);
18
+ return work();
19
+ });
20
+ }
21
+ return { rpc, mutationRpc };
22
+ }
23
+ function requestContext(getRequest) {
24
+ try {
25
+ const request = getRequest?.();
26
+ return request ? { method: request.method, path: new URL(request.url).pathname } : {};
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/server/rpc.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,SAAS,CAAC,OAAO,GAAe,EAAE;IAChD,KAAK,UAAU,GAAG,CAAI,IAA0B;QAC9C,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAA;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,mBAAmB,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;YAC5H,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;YAC7D,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,SAAS,WAAW,CAAI,IAA0B,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,EAAE;QAClF,OAAO,GAAG,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAChE,OAAO,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAA;YAClC,OAAO,IAAI,EAAE,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAA;AAC7B,CAAC;AAED,SAAS,cAAc,CAAC,UAAuC;IAC7D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,EAAE,CAAA;QAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Upload, type UploadOptions } from 'tus-js-client';
2
+ export type TusUploadProgress = {
3
+ sent: number;
4
+ total: number;
5
+ percent: number;
6
+ };
7
+ export type TusUploadOptions = {
8
+ endpoint: string;
9
+ file: File;
10
+ metadata: Record<string, string>;
11
+ chunkSize?: number;
12
+ retryDelays?: readonly number[];
13
+ fingerprint?: UploadOptions['fingerprint'];
14
+ removeFingerprintOnSuccess?: boolean;
15
+ shouldRetry?: (status: number | undefined, retryAttempt: number) => boolean;
16
+ onProgress?: (progress: TusUploadProgress) => void;
17
+ };
18
+ export type TusUploadResult = {
19
+ responseBody: string;
20
+ responseStatus: number | undefined;
21
+ uploadUrl: string | null;
22
+ };
23
+ export declare function createTusUpload(options: TusUploadOptions): Upload;
24
+ export declare function startTusUpload(upload: Upload, resume?: boolean): Promise<TusUploadResult>;
25
+ export declare function uploadWithTus(options: TusUploadOptions, resume?: boolean): Promise<TusUploadResult>;
26
+ export declare function tusResponseMessage(error: unknown): string | undefined;
27
+ export declare function tusResponse(error: unknown): {
28
+ status: number | undefined;
29
+ body: string;
30
+ } | undefined;
@@ -0,0 +1,77 @@
1
+ import { defaultOptions, Upload } from 'tus-js-client';
2
+ export function createTusUpload(options) {
3
+ return new Upload(options.file, {
4
+ endpoint: options.endpoint,
5
+ metadata: options.metadata,
6
+ retryDelays: [...(options.retryDelays ?? [0, 1_000, 3_000, 5_000])],
7
+ ...(options.chunkSize === undefined ? {} : { chunkSize: options.chunkSize }),
8
+ ...(options.fingerprint === undefined ? {} : { fingerprint: options.fingerprint }),
9
+ ...(options.removeFingerprintOnSuccess === undefined ? {} : { removeFingerprintOnSuccess: options.removeFingerprintOnSuccess }),
10
+ onShouldRetry: (error, retryAttempt, uploadOptions) => {
11
+ const status = error.originalResponse?.getStatus();
12
+ if (options.shouldRetry && !options.shouldRetry(status, retryAttempt))
13
+ return false;
14
+ return defaultOptions.onShouldRetry?.(error, retryAttempt, uploadOptions) === true;
15
+ },
16
+ onProgress: (sent, total) => options.onProgress?.({ sent, total, percent: total ? Math.round((sent / total) * 100) : 0 }),
17
+ });
18
+ }
19
+ export async function startTusUpload(upload, resume = true) {
20
+ if (resume) {
21
+ const previous = await upload.findPreviousUploads();
22
+ if (previous[0])
23
+ upload.resumeFromPreviousUpload(previous[0]);
24
+ }
25
+ return new Promise((resolve, reject) => {
26
+ const previousError = upload.options.onError;
27
+ const previousSuccess = upload.options.onSuccess;
28
+ upload.options.onError = (error) => {
29
+ try {
30
+ previousError?.(error);
31
+ }
32
+ finally {
33
+ reject(error);
34
+ }
35
+ };
36
+ upload.options.onSuccess = (event) => {
37
+ try {
38
+ previousSuccess?.(event);
39
+ resolve({
40
+ responseBody: event.lastResponse.getBody(),
41
+ responseStatus: event.lastResponse.getStatus(),
42
+ uploadUrl: upload.url,
43
+ });
44
+ }
45
+ catch (error) {
46
+ reject(error);
47
+ }
48
+ };
49
+ upload.start();
50
+ });
51
+ }
52
+ export function uploadWithTus(options, resume = true) {
53
+ return startTusUpload(createTusUpload(options), resume);
54
+ }
55
+ export function tusResponseMessage(error) {
56
+ const response = responseFromError(error);
57
+ if (response)
58
+ return response.body;
59
+ const message = error instanceof Error ? error.message : undefined;
60
+ return message ? /response text: ([^,]+)/.exec(message)?.[1]?.trim() : undefined;
61
+ }
62
+ export function tusResponse(error) {
63
+ return responseFromError(error);
64
+ }
65
+ function responseFromError(error) {
66
+ if (!error || typeof error !== 'object' || !('originalResponse' in error))
67
+ return undefined;
68
+ const response = error.originalResponse;
69
+ if (!response || typeof response !== 'object' || !('getStatus' in response) || !('getBody' in response))
70
+ return undefined;
71
+ if (typeof response.getStatus !== 'function' || typeof response.getBody !== 'function')
72
+ return undefined;
73
+ const status = response.getStatus();
74
+ const body = response.getBody();
75
+ return { status: typeof status === 'number' ? status : undefined, body: typeof body === 'string' ? body : '' };
76
+ }
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/uploads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAsB,MAAM,eAAe,CAAA;AAsB1E,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnE,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAClF,GAAG,CAAC,OAAO,CAAC,0BAA0B,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,0BAA0B,EAAE,OAAO,CAAC,0BAA0B,EAAE,CAAC;QAC/H,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE;YACpD,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,EAAE,SAAS,EAAE,CAAA;YAClD,IAAI,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC;gBAAE,OAAO,KAAK,CAAA;YACnF,OAAO,cAAc,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC,KAAK,IAAI,CAAA;QACpF,CAAC;QACD,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1H,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,MAAM,GAAG,IAAI;IAChE,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAA;QACnD,IAAI,QAAQ,CAAC,CAAC,CAAC;YAAE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAA;QAC5C,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAA;QAChD,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YACjC,IAAI,CAAC;gBACH,aAAa,EAAE,CAAC,KAAK,CAAC,CAAA;YACxB,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,KAAK,CAAC,CAAA;YACf,CAAC;QACH,CAAC,CAAA;QACD,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;YACnC,IAAI,CAAC;gBACH,eAAe,EAAE,CAAC,KAAK,CAAC,CAAA;gBACxB,OAAO,CAAC;oBACN,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE;oBAC1C,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE;oBAC9C,SAAS,EAAE,MAAM,CAAC,GAAG;iBACtB,CAAC,CAAA;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAA;YACf,CAAC;QACH,CAAC,CAAA;QACD,MAAM,CAAC,KAAK,EAAE,CAAA;IAChB,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB,EAAE,MAAM,GAAG,IAAI;IACpE,OAAO,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;IACzC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAA;IAClC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IAClE,OAAO,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAA;AACjC,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,kBAAkB,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3F,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAA;IACvC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IACzH,IAAI,OAAO,QAAQ,CAAC,SAAS,KAAK,UAAU,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,SAAS,CAAA;IACxG,MAAM,MAAM,GAAY,QAAQ,CAAC,SAAS,EAAE,CAAA;IAC5C,MAAM,IAAI,GAAY,QAAQ,CAAC,OAAO,EAAE,CAAA;IACxC,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AAChH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "ras-stack",
3
+ "version": "0.1.0",
4
+ "description": "Composable full-stack primitives shared across Richard Solomou's applications.",
5
+ "keywords": [
6
+ "authentication",
7
+ "centrifugo",
8
+ "fullstack",
9
+ "tanstack",
10
+ "tus"
11
+ ],
12
+ "homepage": "https://github.com/richardsolomou/ras-stack#readme",
13
+ "bugs": "https://github.com/richardsolomou/ras-stack/issues",
14
+ "license": "AGPL-3.0-only",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/richardsolomou/ras-stack.git"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "config"
22
+ ],
23
+ "type": "module",
24
+ "sideEffects": false,
25
+ "exports": {
26
+ "./auth": {
27
+ "types": "./dist/auth/index.d.ts",
28
+ "default": "./dist/auth/index.js"
29
+ },
30
+ "./email": {
31
+ "types": "./dist/email/index.d.ts",
32
+ "default": "./dist/email/index.js"
33
+ },
34
+ "./realtime": {
35
+ "types": "./dist/realtime/index.d.ts",
36
+ "default": "./dist/realtime/index.js"
37
+ },
38
+ "./server": {
39
+ "types": "./dist/server/index.d.ts",
40
+ "default": "./dist/server/index.js"
41
+ },
42
+ "./uploads": {
43
+ "types": "./dist/uploads/index.d.ts",
44
+ "default": "./dist/uploads/index.js"
45
+ },
46
+ "./config/oxlint": "./config/oxlint.json",
47
+ "./config/typescript/browser": "./config/typescript/browser.json",
48
+ "./config/typescript/library": "./config/typescript/library.json",
49
+ "./config/typescript/tanstack": "./config/typescript/tanstack.json"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "build": "tsc -p tsconfig.build.json",
56
+ "config:check": "tsc -p test/config-consumer/tsconfig.json",
57
+ "typecheck": "tsc --noEmit",
58
+ "lint": "oxlint --type-aware --deny-warnings .",
59
+ "format": "oxfmt --write .",
60
+ "format:check": "oxfmt --check .",
61
+ "test": "vitest run",
62
+ "check": "pnpm format:check && pnpm lint && pnpm config:check && pnpm typecheck && pnpm test && pnpm build"
63
+ },
64
+ "devDependencies": {
65
+ "@types/node": "^26.0.0",
66
+ "@types/nodemailer": "^8.0.1",
67
+ "nodemailer": "^9.0.3",
68
+ "oxfmt": "^0.59.0",
69
+ "oxlint": "^1.74.0",
70
+ "oxlint-tsgolint": "^7.0.2001",
71
+ "tus-js-client": "^4.3.1",
72
+ "typescript": "^7.0.2",
73
+ "vitest": "^4.1.10"
74
+ },
75
+ "peerDependencies": {
76
+ "nodemailer": ">=9 <10",
77
+ "tus-js-client": ">=4 <5"
78
+ },
79
+ "peerDependenciesMeta": {
80
+ "nodemailer": {
81
+ "optional": true
82
+ },
83
+ "tus-js-client": {
84
+ "optional": true
85
+ }
86
+ },
87
+ "engines": {
88
+ "node": ">=24 <25"
89
+ },
90
+ "packageManager": "pnpm@11.15.0"
91
+ }