1+ import {
2+ type ApiSnapshotDownload ,
3+ type RESTGetApiSnapshotListResult ,
4+ type RESTGetApiSnapshotResult ,
5+ type RESTGetApiSnapshotVersionResult ,
6+ type RESTPostApiSnapshotResult ,
7+ Routes ,
8+ } from "@discloudapp/api-types/v2" ;
9+ import { DiscloudAPIError } from "@discloudapp/rest" ;
10+ import { constants } from "http2" ;
11+ import type DiscloudApp from "../discloudApp/DiscloudApp" ;
12+ import Snapshot from "../structures/Snapshot" ;
13+ import { validateNonEmptyString } from "../util/assertions" ;
14+ import BaseSnapshotsManager from "./BaseSnapshotsManager" ;
15+
16+ export interface FetchSnapshotsOptions {
17+ page ?: number ;
18+ limit ?: number ;
19+ summary ?: boolean ;
20+ }
21+
22+ /**
23+ * Manager for versioned snapshots on Discloud
24+ */
25+ export default class SnapshotsManager extends BaseSnapshotsManager <
26+ typeof Snapshot
27+ > {
28+ constructor ( discloudApp : DiscloudApp ) {
29+ super ( discloudApp , Snapshot ) ;
30+ }
31+
32+ /**
33+ * Create a new versioned snapshot for an app
34+ *
35+ * @throws `400`
36+ * @throws `403`
37+ * @throws `404` not found
38+ * @throws `409` app busy
39+ *
40+ * @param appID - Your app id
41+ */
42+ async create ( appID : string ) {
43+ validateNonEmptyString ( appID ) ;
44+
45+ const data = await this . discloudApp . rest . post < RESTPostApiSnapshotResult > (
46+ Routes . snapshot ( appID ) ,
47+ ) ;
48+
49+ return this . _add ( {
50+ appId : appID ,
51+ version : data . snapshot . version ,
52+ size : data . snapshot . size ,
53+ } ) ;
54+ }
55+
56+ /**
57+ * Generate a temporary download url for a specific snapshot version
58+ *
59+ * @throws `400`
60+ * @throws `404` not found
61+ *
62+ * @param appID - Your app id
63+ * @param version - Snapshot version in `YYYYMMDD-HHMMSS` format
64+ */
65+ async getDownloadUrl (
66+ appID : string ,
67+ version : string ,
68+ ) : Promise < ApiSnapshotDownload > {
69+ validateNonEmptyString ( appID ) ;
70+ validateNonEmptyString ( version ) ;
71+
72+ const data =
73+ await this . discloudApp . rest . get < RESTGetApiSnapshotVersionResult > (
74+ Routes . snapshot ( appID , version ) ,
75+ ) ;
76+
77+ return data . download ;
78+ }
79+
80+ /**
81+ * Get all versioned snapshots for an app on Discloud
82+ *
83+ * @throws `400`
84+ * @throws `404` not found
85+ *
86+ * @param appID - Your app id
87+ */
88+ async fetch ( appID : string ) : Promise < Map < string , Snapshot > > ;
89+ /**
90+ * Get all versioned snapshots of the authenticated user
91+ *
92+ * @throws `400`
93+ */
94+ async fetch (
95+ appID ?: "all" ,
96+ options ?: FetchSnapshotsOptions ,
97+ ) : Promise < Map < string , Snapshot > > ;
98+ async fetch ( appID : string = "all" , options : FetchSnapshotsOptions = { } ) {
99+ if ( appID === "all" ) return this . #fetchMany( options ) ;
100+
101+ validateNonEmptyString ( appID ) ;
102+
103+ try {
104+ const data = await this . discloudApp . rest . get < RESTGetApiSnapshotResult > (
105+ Routes . snapshot ( appID ) ,
106+ ) ;
107+
108+ this . _clear (
109+ data . versions . map ( ( version ) => ( { appId : appID , ...version } ) ) ,
110+ ) ;
111+
112+ return this . _addMany (
113+ data . versions . map ( ( version ) => ( { appId : appID , ...version } ) ) ,
114+ ) ;
115+ } catch ( error ) {
116+ if ( error instanceof DiscloudAPIError ) {
117+ switch ( error . code ) {
118+ case constants . HTTP_STATUS_NOT_FOUND :
119+ this . _clear ( ) ;
120+ break ;
121+
122+ default :
123+ throw error ;
124+ }
125+ }
126+
127+ throw error ;
128+ }
129+ }
130+
131+ async #fetchMany( options : FetchSnapshotsOptions ) {
132+ const query : Record < string , string > = { } ;
133+
134+ if ( options . page !== undefined ) query . page = String ( options . page ) ;
135+ if ( options . limit !== undefined ) query . limit = String ( options . limit ) ;
136+ if ( options . summary !== undefined ) query . summary = String ( options . summary ) ;
137+
138+ try {
139+ const data =
140+ await this . discloudApp . rest . get < RESTGetApiSnapshotListResult > (
141+ Routes . snapshot ( ) ,
142+ { query } ,
143+ ) ;
144+
145+ return this . _addMany (
146+ data . backups . map ( ( backup ) => ( { appId : backup . appID , ...backup } ) ) ,
147+ ) ;
148+ } catch ( error ) {
149+ if ( error instanceof DiscloudAPIError ) {
150+ switch ( error . code ) {
151+ case constants . HTTP_STATUS_NOT_FOUND :
152+ this . _clear ( ) ;
153+ break ;
154+
155+ default :
156+ throw error ;
157+ }
158+ }
159+
160+ throw error ;
161+ }
162+ }
163+ }
0 commit comments