@filefreak.io/sdk 0.0.0-stage → 0.2.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.
- package/README.md +189 -2
- package/dist/client.d.ts +78 -0
- package/dist/client.js +168 -0
- package/dist/generated.d.ts +1060 -0
- package/dist/generated.js +329 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +17 -0
- package/dist/links.d.ts +72 -0
- package/dist/links.js +355 -0
- package/dist/md5.d.ts +18 -0
- package/dist/md5.js +130 -0
- package/dist/node.d.ts +36 -0
- package/dist/node.js +124 -0
- package/dist/ranges.d.ts +34 -0
- package/dist/ranges.js +303 -0
- package/dist/reader.d.ts +76 -0
- package/dist/reader.js +510 -0
- package/dist/shards.d.ts +59 -0
- package/dist/shards.js +140 -0
- package/dist/transport.d.ts +61 -0
- package/dist/transport.js +173 -0
- package/dist/uploads.d.ts +53 -0
- package/dist/uploads.js +259 -0
- package/package.json +27 -4
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// The developer API's endpoints, and the shapes they take and answer with,
|
|
2
|
+
// written out from the table in api/src/routes/v1.ts by
|
|
3
|
+
// api/src/scripts/clientTypes.ts. Change the table, not this, and run
|
|
4
|
+
// `npm run clients:types`: tests/checks/clients-are-current.mjs fails while
|
|
5
|
+
// this is behind it.
|
|
6
|
+
/** Every endpoint, by the name its entry gives it. */
|
|
7
|
+
export const OPERATIONS = {
|
|
8
|
+
"files.list": { method: "GET", path: "/v1/files", idempotent: false, repeatable: false },
|
|
9
|
+
"files.byPath": { method: "GET", path: "/v1/files/by-path", idempotent: false, repeatable: false },
|
|
10
|
+
"files.get": { method: "GET", path: "/v1/files/:id", idempotent: false, repeatable: false },
|
|
11
|
+
"files.update": { method: "PATCH", path: "/v1/files/:id", idempotent: false, repeatable: false },
|
|
12
|
+
"files.delete": { method: "DELETE", path: "/v1/files/:id", idempotent: false, repeatable: false },
|
|
13
|
+
"files.restore": { method: "POST", path: "/v1/files/:id/restore", idempotent: false, repeatable: false },
|
|
14
|
+
"folders.create": { method: "POST", path: "/v1/folders", idempotent: true, repeatable: false },
|
|
15
|
+
"tree.list": { method: "GET", path: "/v1/tree", idempotent: false, repeatable: false },
|
|
16
|
+
"changes.list": { method: "GET", path: "/v1/changes", idempotent: false, repeatable: false },
|
|
17
|
+
"uploads.begin": { method: "POST", path: "/v1/uploads", idempotent: true, repeatable: false },
|
|
18
|
+
"uploads.get": { method: "GET", path: "/v1/uploads/:id", idempotent: false, repeatable: false },
|
|
19
|
+
"uploads.parts": { method: "GET", path: "/v1/uploads/:id/parts", idempotent: false, repeatable: false },
|
|
20
|
+
"uploads.complete": { method: "POST", path: "/v1/uploads/:id/complete", idempotent: false, repeatable: true },
|
|
21
|
+
"uploads.cancel": { method: "DELETE", path: "/v1/uploads/:id", idempotent: false, repeatable: false },
|
|
22
|
+
"files.downloadUrl": { method: "GET", path: "/v1/files/:id/download", idempotent: false, repeatable: false },
|
|
23
|
+
"files.shards": { method: "GET", path: "/v1/files/:id/shards", idempotent: false, repeatable: false },
|
|
24
|
+
"files.image": { method: "GET", path: "/v1/files/:id/image", idempotent: false, repeatable: false },
|
|
25
|
+
"usage.get": { method: "GET", path: "/v1/usage", idempotent: false, repeatable: false },
|
|
26
|
+
"me.get": { method: "GET", path: "/v1/me", idempotent: false, repeatable: false },
|
|
27
|
+
"shares.create": { method: "POST", path: "/v1/shares", idempotent: true, repeatable: false },
|
|
28
|
+
"shares.list": { method: "GET", path: "/v1/shares", idempotent: false, repeatable: false },
|
|
29
|
+
"shares.revoke": { method: "DELETE", path: "/v1/shares/:id", idempotent: false, repeatable: false },
|
|
30
|
+
"sites.list": { method: "GET", path: "/v1/sites", idempotent: false, repeatable: false },
|
|
31
|
+
"sites.create": { method: "POST", path: "/v1/sites", idempotent: true, repeatable: false },
|
|
32
|
+
"sites.get": { method: "GET", path: "/v1/sites/:id", idempotent: false, repeatable: false },
|
|
33
|
+
"sites.startDeploy": { method: "POST", path: "/v1/sites/:id/deploys", idempotent: true, repeatable: false },
|
|
34
|
+
"sites.declareFiles": { method: "POST", path: "/v1/sites/deploys/:id/files", idempotent: true, repeatable: false },
|
|
35
|
+
"sites.sendAgain": { method: "POST", path: "/v1/sites/deploys/:id/send", idempotent: false, repeatable: true },
|
|
36
|
+
"sites.finishDeploy": { method: "POST", path: "/v1/sites/deploys/:id/finish", idempotent: false, repeatable: true },
|
|
37
|
+
"sites.removeDeploy": { method: "DELETE", path: "/v1/sites/deploys/:id", idempotent: false, repeatable: false },
|
|
38
|
+
"sites.setLive": { method: "POST", path: "/v1/sites/:id/live", idempotent: false, repeatable: true },
|
|
39
|
+
"tokens.create": { method: "POST", path: "/v1/tokens", idempotent: false, repeatable: true },
|
|
40
|
+
};
|
|
41
|
+
/** Every endpoint as a function, grouped by what it is about. */
|
|
42
|
+
export function bind(call) {
|
|
43
|
+
return {
|
|
44
|
+
files: {
|
|
45
|
+
/**
|
|
46
|
+
* List a folder.
|
|
47
|
+
*
|
|
48
|
+
* What is in a folder, a page at a time: folders first, then files, each by name. Pass nextCursor back as cursor for the next page; when it is null there is no more. Things in the trash are not listed. A page never repeats or skips something because of what was added or removed between two requests.
|
|
49
|
+
*
|
|
50
|
+
* GET /v1/files. Needs the scope files:read.
|
|
51
|
+
*/
|
|
52
|
+
list: (query, options) => call("files.list", { query }, options),
|
|
53
|
+
/**
|
|
54
|
+
* A file or folder by its path.
|
|
55
|
+
*
|
|
56
|
+
* Found by the names of the folders down to it from the top of the app (or of the folder the key is confined to), separated by /. A name matches whatever its case, as names in one folder do. Nothing in the trash is found, nor anything inside something that is.
|
|
57
|
+
*
|
|
58
|
+
* GET /v1/files/by-path. Needs the scope files:read.
|
|
59
|
+
*/
|
|
60
|
+
byPath: (query, options) => call("files.byPath", { query }, options),
|
|
61
|
+
/**
|
|
62
|
+
* One file or folder.
|
|
63
|
+
*
|
|
64
|
+
* By its id. Something in the trash is still returned, with trashedAt set.
|
|
65
|
+
*
|
|
66
|
+
* GET /v1/files/:id. Needs the scope files:read.
|
|
67
|
+
*/
|
|
68
|
+
get: (id, options) => call("files.get", { params: { id } }, options),
|
|
69
|
+
/**
|
|
70
|
+
* Rename, move, or make public.
|
|
71
|
+
*
|
|
72
|
+
* Any of the three, in one request. They are applied in that order, each as its own change: if the second is refused the first has still happened, and the answer says which was refused. Moving a folder moves everything in it and is one change however much that is. Making a folder public makes everything in it public, except what has a setting of its own.
|
|
73
|
+
*
|
|
74
|
+
* PATCH /v1/files/:id. Needs the scope files:write.
|
|
75
|
+
*/
|
|
76
|
+
update: (id, body, options) => call("files.update", { params: { id }, body }, options),
|
|
77
|
+
/**
|
|
78
|
+
* Put in the trash, or delete for good.
|
|
79
|
+
*
|
|
80
|
+
* Without permanent, the file or folder goes to the trash: it can be restored, it still counts toward storage, and it is removed for good after thirty days. With permanent=true it is removed now, with everything inside it, and cannot be brought back.
|
|
81
|
+
*
|
|
82
|
+
* DELETE /v1/files/:id. Needs the scope files:delete.
|
|
83
|
+
*/
|
|
84
|
+
delete: (id, query, options) => call("files.delete", { params: { id }, query }, options),
|
|
85
|
+
/**
|
|
86
|
+
* Take out of the trash.
|
|
87
|
+
*
|
|
88
|
+
* It goes back where it was. If that folder has gone it goes to the top, and if its name has been taken in the meantime it comes back with a number after it.
|
|
89
|
+
*
|
|
90
|
+
* POST /v1/files/:id/restore. Needs the scope files:write.
|
|
91
|
+
*/
|
|
92
|
+
restore: (id, options) => call("files.restore", { params: { id } }, options),
|
|
93
|
+
/**
|
|
94
|
+
* An address to download a file from.
|
|
95
|
+
*
|
|
96
|
+
* A short-lived address on storage itself. Anybody holding it can fetch the file until it expires, with no key, so it can be handed to a browser. Each one issued counts the file's size toward the month's downloads. For an address that does not expire, make the file public and use its publicUrl. A file under Shard Protection has no address: it is answered with 409 shard_protected, and read through its map with files.shards.
|
|
97
|
+
*
|
|
98
|
+
* GET /v1/files/:id/download. Needs the scope files:read.
|
|
99
|
+
*/
|
|
100
|
+
downloadUrl: (id, query, options) => call("files.downloadUrl", { params: { id }, query }, options),
|
|
101
|
+
/**
|
|
102
|
+
* A protected file's map.
|
|
103
|
+
*
|
|
104
|
+
* A file under Shard Protection is kept as fragments, each sealed with the file's own key and stored across several storage accounts. Its map says where each fragment is, up to 1,000 at a time, with the key. Fetch each fragment from its address (no key: the address is the permission), check and open it as the SDK's openFragment does, and write it at its place. The first page counts the file's size toward the month's downloads; later pages count nothing. Addresses work for four hours: before then, ask for the page again from the first fragment not yet fetched. The key is in this answer and nowhere else. This API never keeps it, and neither should a program, beyond the read.
|
|
105
|
+
*
|
|
106
|
+
* GET /v1/files/:id/shards. Needs the scope files:read.
|
|
107
|
+
*/
|
|
108
|
+
shards: (id, query, options) => call("files.shards", { params: { id }, query }, options),
|
|
109
|
+
/**
|
|
110
|
+
* An image at a smaller size.
|
|
111
|
+
*
|
|
112
|
+
* A copy of an image no more than size pixels on its longest side, as WebP, with the camera's metadata removed. The sizes are 64, 128, 256, 512, 1024 and no others. Each is made once, the first time it is asked for, and kept: until it has been made the answer is 202. Name the sizes when the image is uploaded and they are ready by the time they are wanted. For a public file, add ?size= to its publicUrl. A file under Shard Protection has no smaller copies, and is answered with 409 shard_protected.
|
|
113
|
+
*
|
|
114
|
+
* GET /v1/files/:id/image. Needs the scope files:read.
|
|
115
|
+
*/
|
|
116
|
+
image: (id, query, options) => call("files.image", { params: { id }, query }, options),
|
|
117
|
+
},
|
|
118
|
+
folders: {
|
|
119
|
+
/**
|
|
120
|
+
* Make a folder.
|
|
121
|
+
*
|
|
122
|
+
* Folders can be nested up to 32 deep. With ifExists=use, a folder of that name that is already there is returned and nothing is made, which is what a program that makes its folders on every start wants.
|
|
123
|
+
*
|
|
124
|
+
* POST /v1/folders. Needs the scope files:write. Honours an Idempotency-Key.
|
|
125
|
+
*/
|
|
126
|
+
create: (body, options) => call("folders.create", { body }, options),
|
|
127
|
+
},
|
|
128
|
+
tree: {
|
|
129
|
+
/**
|
|
130
|
+
* Everything under a folder.
|
|
131
|
+
*
|
|
132
|
+
* Every file and folder under a folder, at every level, a page at a time, each folder before what is inside it. Pass nextCursor back as cursor for the next page; when it is null there is no more. Things in the trash are not listed. Every page carries changesCursor: the place in GET /v1/changes from before the first page was read. Something that changes while the pages are being read may be listed or not, and is in the changes after that place either way. It is null for a key confined to a folder, which cannot follow the changes.
|
|
133
|
+
*
|
|
134
|
+
* GET /v1/tree. Needs the scope files:read.
|
|
135
|
+
*/
|
|
136
|
+
list: (query, options) => call("tree.list", { query }, options),
|
|
137
|
+
},
|
|
138
|
+
changes: {
|
|
139
|
+
/**
|
|
140
|
+
* What has changed.
|
|
141
|
+
*
|
|
142
|
+
* Every change to the app's files and folders after cursor, oldest first, each saying what the thing is now. A folder's change stands for everything in it: a folder moved, put in the trash or deleted is one change, and what is inside goes with it. Without cursor, no changes and the cursor for now. Pass cursor back each time; while more is true, ask again at once. With wait, an answer that would be empty waits up to that many seconds for something to change, and comes back empty, with the same cursor, if nothing does.
|
|
143
|
+
*
|
|
144
|
+
* To keep a copy: list everything with GET /v1/tree and keep its changesCursor, then apply each change in order. A change that is not live, or whose parentId is a folder the copy does not have, takes that thing and everything inside it out of the copy. A live change puts it in, or moves or renames it; a folder that was not in the copy is then listed with GET /v1/tree?parent= for what it holds, and if that is answered 404 the folder has gone since, which a later change says. A file whose revision has gone up has new content. Changes are kept for 30 days, and a cursor from before that is answered 410 cursor_expired: start again from a listing. A key confined to a folder cannot follow the changes, and lists its folder again instead.
|
|
145
|
+
*
|
|
146
|
+
* While the service is asleep, after a while with nobody using it, nothing can change, and a question with a cursor is answered without waking it: no changes, the same cursor, after the wait asked for. Asking is not counted as using the service, so a program that asks all night does not keep it awake.
|
|
147
|
+
*
|
|
148
|
+
* GET /v1/changes. Needs the scope files:read.
|
|
149
|
+
*/
|
|
150
|
+
list: (query, options) => call("changes.list", { query }, options),
|
|
151
|
+
},
|
|
152
|
+
uploads: {
|
|
153
|
+
/**
|
|
154
|
+
* Begin an upload.
|
|
155
|
+
*
|
|
156
|
+
* Says what is about to be sent, and answers with where to send it. A file's bytes never pass through this API: they go straight to storage, in parts, each with a plain PUT to the address given for it. The first addresses come back here; ask for the rest as they are needed. Then complete the upload, and it becomes a file.
|
|
157
|
+
*
|
|
158
|
+
* The room is set aside now, so an upload that would not fit is refused before a byte is sent. The parts can be sent by anything that can make a PUT request, including a browser that has never seen the API key: hand it the addresses.
|
|
159
|
+
*
|
|
160
|
+
* Into a folder under Shard Protection, which its owner turns on from the website, a file lands as an ordinary file, as it would anywhere else, and the service protects it within a few minutes: its content, and every kept version, are spread over the storage lanes as fragments. Until then it can be read like any other file. From then on it is read through its map (files.shards), and its clientSha256 is null. An upload from a program is not sealed as it is sent yet.
|
|
161
|
+
*
|
|
162
|
+
* POST /v1/uploads. Needs the scope files:write. Honours an Idempotency-Key.
|
|
163
|
+
*/
|
|
164
|
+
begin: (body, options) => call("uploads.begin", { body }, options),
|
|
165
|
+
/**
|
|
166
|
+
* An upload, and which parts have arrived.
|
|
167
|
+
*
|
|
168
|
+
* For carrying on after an interruption: storage itself says which parts it has, so nothing the client remembered is needed.
|
|
169
|
+
*
|
|
170
|
+
* GET /v1/uploads/:id. Needs the scope files:write.
|
|
171
|
+
*/
|
|
172
|
+
get: (id, options) => call("uploads.get", { params: { id } }, options),
|
|
173
|
+
/**
|
|
174
|
+
* Addresses for more parts.
|
|
175
|
+
*
|
|
176
|
+
* Addresses are given out a window at a time and each lasts half an hour. Ask again for any that have run out.
|
|
177
|
+
*
|
|
178
|
+
* GET /v1/uploads/:id/parts. Needs the scope files:write.
|
|
179
|
+
*/
|
|
180
|
+
parts: (id, query, options) => call("uploads.parts", { params: { id }, query }, options),
|
|
181
|
+
/**
|
|
182
|
+
* Finish an upload.
|
|
183
|
+
*
|
|
184
|
+
* Turns the parts into a file. Safe to call again: a second call for an upload that has finished answers with the same file. For a very large file storage may still be putting it together, and the answer is then 202 with how long to wait before asking again.
|
|
185
|
+
*
|
|
186
|
+
* POST /v1/uploads/:id/complete. Needs the scope files:write. Safe to send again.
|
|
187
|
+
*/
|
|
188
|
+
complete: (id, body, options) => call("uploads.complete", { params: { id }, body }, options),
|
|
189
|
+
/**
|
|
190
|
+
* Cancel an upload.
|
|
191
|
+
*
|
|
192
|
+
* Whatever had arrived is deleted, and the room it held comes back at once.
|
|
193
|
+
*
|
|
194
|
+
* DELETE /v1/uploads/:id. Needs the scope files:write.
|
|
195
|
+
*/
|
|
196
|
+
cancel: (id, options) => call("uploads.cancel", { params: { id } }, options),
|
|
197
|
+
},
|
|
198
|
+
usage: {
|
|
199
|
+
/**
|
|
200
|
+
* What the app is using.
|
|
201
|
+
*
|
|
202
|
+
* What this app holds, against the ceiling set for it if there is one; and what the account it belongs to has used this calendar month, across its personal files and all its apps, against what its plan includes. An app's files count toward the account's one storage allowance. For a device signed in with filefreak login, which uses the personal drive, app is null.
|
|
203
|
+
*
|
|
204
|
+
* GET /v1/usage. Needs the scope usage:read.
|
|
205
|
+
*/
|
|
206
|
+
get: (options) => call("usage.get", {}, options),
|
|
207
|
+
},
|
|
208
|
+
me: {
|
|
209
|
+
/**
|
|
210
|
+
* Who this is.
|
|
211
|
+
*
|
|
212
|
+
* The account a key, a token or a device acts for, and what it may do there. A key's program and a page's token are told the account's username and plan, never its email address: only a device signed in with filefreak login, which is the person, is told that.
|
|
213
|
+
*
|
|
214
|
+
* GET /v1/me. Any key may call it.
|
|
215
|
+
*/
|
|
216
|
+
get: (options) => call("me.get", {}, options),
|
|
217
|
+
},
|
|
218
|
+
shares: {
|
|
219
|
+
/**
|
|
220
|
+
* Make a share link.
|
|
221
|
+
*
|
|
222
|
+
* A link that opens one file or folder for whoever holds it, separate from making it public: a private file can have one. It can have a password, an end date and a number of downloads after which it stops. Share links are a person's, so only a device signed in with filefreak login can make them here, as on the website; an app's key cannot. A link to a file under Shard Protection is a shard link: whoever opens it is given the file's key with its map, so their browser can put the file back together, show it and save it. The storage it is kept in still gives nobody anything on its own.
|
|
223
|
+
*
|
|
224
|
+
* POST /v1/shares. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
225
|
+
*/
|
|
226
|
+
create: (body, options) => call("shares.create", { body }, options),
|
|
227
|
+
/**
|
|
228
|
+
* List share links.
|
|
229
|
+
*
|
|
230
|
+
* The links on one file or folder, or every link the account has, newest first. Removed links are not listed. Only a device signed in with filefreak login.
|
|
231
|
+
*
|
|
232
|
+
* GET /v1/shares. Only a device signed in with filefreak login may call it.
|
|
233
|
+
*/
|
|
234
|
+
list: (query, options) => call("shares.list", { query }, options),
|
|
235
|
+
/**
|
|
236
|
+
* Remove a share link.
|
|
237
|
+
*
|
|
238
|
+
* It stops working with the next request, and cannot be brought back. Only a device signed in with filefreak login.
|
|
239
|
+
*
|
|
240
|
+
* DELETE /v1/shares/:id. Only a device signed in with filefreak login may call it.
|
|
241
|
+
*/
|
|
242
|
+
revoke: (id, options) => call("shares.revoke", { params: { id } }, options),
|
|
243
|
+
},
|
|
244
|
+
sites: {
|
|
245
|
+
/**
|
|
246
|
+
* List sites.
|
|
247
|
+
*
|
|
248
|
+
* The account's static sites, by name, with the deploy each serves. A site is a person's, so only a device signed in with filefreak login reaches sites, as on the website; an app's key cannot. Sites are part of Pro.
|
|
249
|
+
*
|
|
250
|
+
* GET /v1/sites. Only a device signed in with filefreak login may call it.
|
|
251
|
+
*/
|
|
252
|
+
list: (options) => call("sites.list", {}, options),
|
|
253
|
+
/**
|
|
254
|
+
* Make a site.
|
|
255
|
+
*
|
|
256
|
+
* A site with no deploy yet. Its name is its address: 3 to 40 lower-case letters, digits and single hyphens, and not a name FileFreak keeps, another account's username, or one that looks like another company's (invalid_site_name, site_name_taken). Refused with sites_need_pro on a plan without sites.
|
|
257
|
+
*
|
|
258
|
+
* POST /v1/sites. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
259
|
+
*/
|
|
260
|
+
create: (body, options) => call("sites.create", { body }, options),
|
|
261
|
+
/**
|
|
262
|
+
* A site and its deploys.
|
|
263
|
+
*
|
|
264
|
+
* A site, and its deploys newest first. A site keeps its 10 newest deploys that have ended besides the live one.
|
|
265
|
+
*
|
|
266
|
+
* GET /v1/sites/:id. Only a device signed in with filefreak login may call it.
|
|
267
|
+
*/
|
|
268
|
+
get: (id, options) => call("sites.get", { params: { id } }, options),
|
|
269
|
+
/**
|
|
270
|
+
* Begin a deploy.
|
|
271
|
+
*
|
|
272
|
+
* Begins a deploy with up to 1000 of its files: each one's path, size and SHA-256. Declare the rest with sites.declareFiles, more set to false on the last list. The answer says which files to send: PUT each one's bytes to its address, then call sites.finishDeploy. Bytes the site has stored already are not asked for. A deploy may have 20000 files, 100 MB each and 1 GB together, and what it adds counts as storage from the moment it is declared (quota_exceeded). An unfinished deploy nothing has asked about for an hour is given up on.
|
|
273
|
+
*
|
|
274
|
+
* POST /v1/sites/:id/deploys. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
275
|
+
*/
|
|
276
|
+
startDeploy: (id, body, options) => call("sites.startDeploy", { params: { id }, body }, options),
|
|
277
|
+
/**
|
|
278
|
+
* Declare more of a deploy's files.
|
|
279
|
+
*
|
|
280
|
+
* The next 1000 files of a deploy at most, as sites.startDeploy takes them. A path declared twice is refused (path_declared_twice).
|
|
281
|
+
*
|
|
282
|
+
* POST /v1/sites/deploys/:id/files. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
283
|
+
*/
|
|
284
|
+
declareFiles: (id, body, options) => call("sites.declareFiles", { params: { id }, body }, options),
|
|
285
|
+
/**
|
|
286
|
+
* Fresh addresses for a deploy's files.
|
|
287
|
+
*
|
|
288
|
+
* New addresses for files of an unfinished deploy whose bytes have not arrived, when the first ones ran out or a finish answered deploy_incomplete. Files whose bytes have arrived are left out.
|
|
289
|
+
*
|
|
290
|
+
* POST /v1/sites/deploys/:id/send. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
291
|
+
*/
|
|
292
|
+
sendAgain: (id, body, options) => call("sites.sendAgain", { params: { id }, body }, options),
|
|
293
|
+
/**
|
|
294
|
+
* Finish a deploy.
|
|
295
|
+
*
|
|
296
|
+
* Storage puts each file in place and is asked its size, and the deploy is ready, and live if live is true. Safe to call again: storage may take longer than one request waits, and the answer is then 202 with how long to wait before asking again. A file whose bytes have not arrived, or arrived at another size, is answered with deploy_incomplete and the SHA-256s to send again.
|
|
297
|
+
*
|
|
298
|
+
* POST /v1/sites/deploys/:id/finish. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
299
|
+
*/
|
|
300
|
+
finishDeploy: (id, body, options) => call("sites.finishDeploy", { params: { id }, body }, options),
|
|
301
|
+
/**
|
|
302
|
+
* Cancel or delete a deploy.
|
|
303
|
+
*
|
|
304
|
+
* Cancels a deploy that is uploading, and what it set aside is given back at once. Deletes one that has ended, with whatever bytes no other deploy of the site uses. Never the live one (deploy_live).
|
|
305
|
+
*
|
|
306
|
+
* DELETE /v1/sites/deploys/:id. Only a device signed in with filefreak login may call it.
|
|
307
|
+
*/
|
|
308
|
+
removeDeploy: (id, options) => call("sites.removeDeploy", { params: { id } }, options),
|
|
309
|
+
/**
|
|
310
|
+
* Choose the live deploy.
|
|
311
|
+
*
|
|
312
|
+
* Makes a ready deploy the one visitors are served, which is also how a site is rolled back; null takes the site offline. Visitors see the change within a minute.
|
|
313
|
+
*
|
|
314
|
+
* POST /v1/sites/:id/live. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
315
|
+
*/
|
|
316
|
+
setLive: (id, body, options) => call("sites.setLive", { params: { id }, body }, options),
|
|
317
|
+
},
|
|
318
|
+
tokens: {
|
|
319
|
+
/**
|
|
320
|
+
* A token for a web page.
|
|
321
|
+
*
|
|
322
|
+
* A key belongs on a server, and one sent from a web page is refused, because anybody who opens the page can read it. A page that should reach this API itself, to upload straight from the browser or to list a folder, is given a token instead: the server makes one with its key and hands it to the page, which sends it as it would a key. A token may do what its key may, or less: the scopes asked for, inside the folder asked for, until it expires. It is checked against its key on every request, so revoking the key stops its tokens at once, and its calls count as the key's. Nothing about a token is kept, so making one is safe to send again. A token cannot make another. Once Pro has ended and a key can only read, it can still make tokens, which can only read too.
|
|
323
|
+
*
|
|
324
|
+
* POST /v1/tokens. Any key may call it. Safe to send again.
|
|
325
|
+
*/
|
|
326
|
+
create: (body, options) => call("tokens.create", { body }, options),
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FileFreak, Walk, type DownloadOptions, type FollowOptions } from "./client.js";
|
|
2
|
+
export * from "./generated.js";
|
|
3
|
+
export { get, type GetOptions, type Got, type Into, type LinkedFile } from "./links.js";
|
|
4
|
+
export { type Sink } from "./ranges.js";
|
|
5
|
+
export { openFragment, sealFragment, SHARD_OVERHEAD, SHARD_VERSION, ShardError, shardKey, ShardLayout, type FragmentAt, type ShardErrorCode, type ShardKey, } from "./shards.js";
|
|
6
|
+
export { FileFreakError, type CallOptions, type ClientOptions, type TokenSource } from "./transport.js";
|
|
7
|
+
export { UploadStopped, type Source, type UploadOptions } from "./uploads.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @filefreak.io/sdk: FileFreak's developer API, for Node and the browser.
|
|
2
|
+
//
|
|
3
|
+
// const ff = new FileFreak({ apiKey: process.env.FILEFREAK_KEY });
|
|
4
|
+
// const { items } = await ff.files.list();
|
|
5
|
+
//
|
|
6
|
+
// In a web page, give it a token the page's own server made with its key
|
|
7
|
+
// (ff.tokens.create), never the key. Files on disk are in "@filefreak.io/sdk/node".
|
|
8
|
+
//
|
|
9
|
+
// Saving what a share link or a public page holds needs no key at all:
|
|
10
|
+
//
|
|
11
|
+
// await get("https://filefreak.link/share/...", toFolder("downloads"));
|
|
12
|
+
export { FileFreak, Walk } from "./client.js";
|
|
13
|
+
export * from "./generated.js";
|
|
14
|
+
export { get } from "./links.js";
|
|
15
|
+
export { openFragment, sealFragment, SHARD_OVERHEAD, SHARD_VERSION, ShardError, shardKey, ShardLayout, } from "./shards.js";
|
|
16
|
+
export { FileFreakError } from "./transport.js";
|
|
17
|
+
export { UploadStopped } from "./uploads.js";
|
package/dist/links.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type Sink } from "./ranges.js";
|
|
2
|
+
/** A file a link holds, as get() hands it to the function that makes its sink. */
|
|
3
|
+
export interface LinkedFile {
|
|
4
|
+
id: string;
|
|
5
|
+
/**
|
|
6
|
+
* Its name, as whoever shared it wrote it. A link can name any site, and
|
|
7
|
+
* that site can say anything, so never use it as a path unchecked:
|
|
8
|
+
* safeName and toFolder, in "@filefreak.io/sdk/node", check it.
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
/** The folders it is in, from the shared folder, by its name, down. Empty for a link to one file. As unchecked as `name`. */
|
|
12
|
+
folders: string[];
|
|
13
|
+
sizeBytes: number;
|
|
14
|
+
contentType: string | null;
|
|
15
|
+
/** Under Shard Protection: put back together from its map, each part checked as it arrives. */
|
|
16
|
+
protected: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Where get() puts what a link holds: one Sink, for a link to one file, or a function that makes one for each file. */
|
|
19
|
+
export type Into = Sink | ((file: LinkedFile) => Sink | Promise<Sink>);
|
|
20
|
+
export interface GetOptions {
|
|
21
|
+
/** The link's password, for a link that has one. */
|
|
22
|
+
password?: string;
|
|
23
|
+
/** Stops the saving, and aborts the sink of the file being saved. */
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
/** Called as bytes are written, with how many have been and how many there are in all. */
|
|
26
|
+
onProgress?: (writtenBytes: number, totalBytes: number) => void;
|
|
27
|
+
/** Another fetch, for a runtime without one or for tests. */
|
|
28
|
+
fetch?: typeof fetch;
|
|
29
|
+
}
|
|
30
|
+
export interface Got {
|
|
31
|
+
/** What the link is to. */
|
|
32
|
+
kind: "file" | "folder";
|
|
33
|
+
/** Its name, as its sharer wrote it. */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Every file saved, in the order they were saved. */
|
|
36
|
+
files: LinkedFile[];
|
|
37
|
+
/** Their bytes, together. */
|
|
38
|
+
sizeBytes: number;
|
|
39
|
+
}
|
|
40
|
+
/** What a link is to, and the site to ask about it. */
|
|
41
|
+
export type Link = {
|
|
42
|
+
origin: string;
|
|
43
|
+
} & ({
|
|
44
|
+
kind: "share";
|
|
45
|
+
token: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: "public";
|
|
48
|
+
id: string;
|
|
49
|
+
username: string | null;
|
|
50
|
+
});
|
|
51
|
+
export declare const NOT_A_LINK = "That is not a FileFreak share link or public file address.";
|
|
52
|
+
/**
|
|
53
|
+
* The link a web address is: `/share/<token>`, `/public/<username>/<id>`,
|
|
54
|
+
* or a public file's direct address, `/api/public/files/<id>/raw`. On https,
|
|
55
|
+
* or on http for the local stack only.
|
|
56
|
+
*/
|
|
57
|
+
export declare function linkOf(url: string | URL): Link;
|
|
58
|
+
/**
|
|
59
|
+
* Save what a share link or a public page holds, with no key: one file into
|
|
60
|
+
* `into`, a Sink, or a folder and everything in it, each file into the Sink
|
|
61
|
+
* that `into`, a function, makes for it. Resolves once every file has been
|
|
62
|
+
* saved and its sink closed.
|
|
63
|
+
*
|
|
64
|
+
* Takes `https://<host>/share/<token>`, `https://<host>/public/<username>/<id>`
|
|
65
|
+
* and a public file's direct address. A protected file is put back together
|
|
66
|
+
* from its map and checked as it arrives. A failure is a FileFreakError, with
|
|
67
|
+
* the site's code and sentence or one of get's own: not_a_link, not_a_file
|
|
68
|
+
* (a folder's link given one Sink), password_required, not_enough_downloads,
|
|
69
|
+
* too_deep, fragment_damaged or fragment_unavailable. The file being saved
|
|
70
|
+
* when it stops has its sink aborted; files saved before it stay saved.
|
|
71
|
+
*/
|
|
72
|
+
export declare function get(url: string | URL, into: Into, options?: GetOptions): Promise<Got>;
|