@filefreak.io/sdk 0.1.0 → 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 +39 -3
- package/dist/client.d.ts +3 -1
- package/dist/client.js +15 -11
- package/dist/generated.d.ts +76 -21
- package/dist/generated.js +30 -19
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/links.d.ts +72 -0
- package/dist/links.js +355 -0
- package/dist/node.d.ts +20 -0
- package/dist/node.js +79 -6
- package/dist/reader.d.ts +76 -0
- package/dist/reader.js +510 -0
- package/dist/shards.d.ts +1 -1
- package/dist/uploads.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,8 +6,10 @@ later and in browsers. No dependencies.
|
|
|
6
6
|
Every endpoint is a function, typed from the same table the API is built
|
|
7
7
|
from. Around them: uploads sent straight to storage in parts and carried on
|
|
8
8
|
after an interruption, downloads fetched in ranges, listings and changes read
|
|
9
|
-
to the end,
|
|
10
|
-
|
|
9
|
+
to the end, files under Shard Protection read through their maps, what a
|
|
10
|
+
share link holds saved with no key, and requests sent again only when that
|
|
11
|
+
cannot make anything twice. The reference is at
|
|
12
|
+
https://filefreak.io/developers/reference.
|
|
11
13
|
|
|
12
14
|
## On a server
|
|
13
15
|
|
|
@@ -30,6 +32,8 @@ const bytes = await ff.bytes(file.id); // for a file small enough to hold in mem
|
|
|
30
32
|
`fromPath` reads the file a part at a time as it is sent, so a file larger
|
|
31
33
|
than memory is fine. `toPath` writes beside the file and gives it its name
|
|
32
34
|
only once every byte is there: a download that fails leaves nothing behind.
|
|
35
|
+
A file under Shard Protection has no address, and `download` and `bytes`
|
|
36
|
+
read it through its map instead, each fragment checked as it arrives.
|
|
33
37
|
|
|
34
38
|
Keep keys on a server. A key sent from a web page is refused.
|
|
35
39
|
|
|
@@ -66,12 +70,44 @@ folder asked for, for a minute to an hour. It is checked against its key on
|
|
|
66
70
|
every request, so revoking the key stops its tokens at once. A token cannot
|
|
67
71
|
make another.
|
|
68
72
|
|
|
73
|
+
## Saving from a link
|
|
74
|
+
|
|
75
|
+
`get` saves what a share link or a public page holds. It needs no key, and
|
|
76
|
+
sends nothing that says who is asking: no key, and from a browser no
|
|
77
|
+
cookies. A file goes into one sink; a folder needs somewhere for each of its
|
|
78
|
+
files, which `toFolder` makes on disk.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { get } from "@filefreak.io/sdk";
|
|
82
|
+
import { toFolder, toPath } from "@filefreak.io/sdk/node";
|
|
83
|
+
|
|
84
|
+
await get("https://filefreak.link/share/...", await toPath("report.pdf"));
|
|
85
|
+
|
|
86
|
+
const got = await get("https://filefreak.link/share/...", toFolder("downloads"), {
|
|
87
|
+
password: "open sesame", // for a link that has one
|
|
88
|
+
onProgress: (written, total) => console.log(`${written} of ${total} bytes`),
|
|
89
|
+
});
|
|
90
|
+
console.log(`${got.files.length} files, ${got.sizeBytes} bytes`);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
It takes a share link, a public file's or folder's page, and a file's direct
|
|
94
|
+
address. A folder comes whole: each file goes to the sink the function makes
|
|
95
|
+
for it, given its name and the folders it is in. Each file saved is one of
|
|
96
|
+
the link's downloads, as on its page, and a link with fewer left than there
|
|
97
|
+
are files saves nothing (`not_enough_downloads`). A file under Shard
|
|
98
|
+
Protection is read through the link's map, and counted once.
|
|
99
|
+
|
|
100
|
+
Every name a link gives is its sharer's, and can be anything: `../../.bashrc`,
|
|
101
|
+
or one that reads backwards. `toFolder` makes each one safe with `safeName`
|
|
102
|
+
before writing, and never writes outside the folder it is given. A program
|
|
103
|
+
that names files from a link itself should use `safeName` too.
|
|
104
|
+
|
|
69
105
|
## Every endpoint
|
|
70
106
|
|
|
71
107
|
The functions are grouped as the reference groups the endpoints:
|
|
72
108
|
`ff.files`, `ff.folders`, `ff.tree`, `ff.changes`, `ff.uploads`, `ff.usage`,
|
|
73
109
|
`ff.me`, `ff.tokens` and `ff.shares` (share links, which only a device signed
|
|
74
|
-
in with `
|
|
110
|
+
in with `filefreak login` may make). Ids in the address come first, then the body or
|
|
75
111
|
the query, then options:
|
|
76
112
|
|
|
77
113
|
```ts
|
package/dist/client.d.ts
CHANGED
|
@@ -66,7 +66,9 @@ export declare class FileFreak {
|
|
|
66
66
|
/**
|
|
67
67
|
* Fetch a file straight from storage into `sink`: as up to six ranges at
|
|
68
68
|
* once for a large one. One download address is asked for, so the file is
|
|
69
|
-
* counted toward the month's downloads once.
|
|
69
|
+
* counted toward the month's downloads once. A file under Shard Protection
|
|
70
|
+
* has no address, and is read through its map instead (files.shards), each
|
|
71
|
+
* fragment checked as it arrives. Resolves to the file.
|
|
70
72
|
*/
|
|
71
73
|
download(id: string, sink: Sink, options?: DownloadOptions): Promise<Item>;
|
|
72
74
|
/** A file's bytes, in memory: for a file small enough to hold. */
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// ranges, and reading a listing or the changes to the end.
|
|
5
5
|
import { bind, OPERATIONS, } from "./generated.js";
|
|
6
6
|
import { fetchRanges } from "./ranges.js";
|
|
7
|
+
import { asItIsKept, readProtected } from "./reader.js";
|
|
7
8
|
import { FileFreakError, sleep, Transport } from "./transport.js";
|
|
8
9
|
import { upload } from "./uploads.js";
|
|
9
10
|
/** How long a follow of the changes waits for one before asking again, unless told. */
|
|
@@ -90,7 +91,9 @@ export class FileFreak {
|
|
|
90
91
|
/**
|
|
91
92
|
* Fetch a file straight from storage into `sink`: as up to six ranges at
|
|
92
93
|
* once for a large one. One download address is asked for, so the file is
|
|
93
|
-
* counted toward the month's downloads once.
|
|
94
|
+
* counted toward the month's downloads once. A file under Shard Protection
|
|
95
|
+
* has no address, and is read through its map instead (files.shards), each
|
|
96
|
+
* fragment checked as it arrives. Resolves to the file.
|
|
94
97
|
*/
|
|
95
98
|
async download(id, sink, options = {}) {
|
|
96
99
|
try {
|
|
@@ -117,18 +120,19 @@ export class FileFreak {
|
|
|
117
120
|
// Nothing to fetch, and an address would count a download of nothing.
|
|
118
121
|
if (item.sizeBytes === 0)
|
|
119
122
|
return;
|
|
120
|
-
const {
|
|
121
|
-
const progress =
|
|
122
|
-
await
|
|
123
|
-
url,
|
|
124
|
-
sizeBytes: item.sizeBytes,
|
|
123
|
+
const { signal, onProgress } = options;
|
|
124
|
+
const progress = onProgress && ((written) => onProgress(written, item.sizeBytes));
|
|
125
|
+
await asItIsKept(item.protected, async () => {
|
|
126
|
+
const { url } = await this.files.downloadUrl(item.id, {}, { signal });
|
|
127
|
+
await fetchRanges({ url, sizeBytes: item.sizeBytes, sink, signal, progress, ranges: options.ranges, fetch: this.transport.fetch, sleep: (ms) => sleep(ms, signal) });
|
|
128
|
+
}, () => readProtected({
|
|
129
|
+
pages: (from, pageSignal) => this.files.shards(item.id, { from }, { signal: pageSignal }),
|
|
125
130
|
sink,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
sizeBytes: item.sizeBytes,
|
|
132
|
+
signal,
|
|
133
|
+
progress,
|
|
129
134
|
fetch: this.transport.fetch,
|
|
130
|
-
|
|
131
|
-
});
|
|
135
|
+
}));
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
/** Every item in a listing, a page at a time. */
|
package/dist/generated.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface Item {
|
|
|
23
23
|
revision: number;
|
|
24
24
|
/** The SHA-256 the uploader gave when it completed the upload of this content, in lower-case hex, or null. The uploader's word: this service never sees a file's bytes and does not check it. */
|
|
25
25
|
clientSha256: string | null;
|
|
26
|
+
/** Whether the file is under Shard Protection: kept as sealed fragments, and read through its map (files.shards) rather than from an address. */
|
|
27
|
+
protected: boolean;
|
|
26
28
|
createdAt: string;
|
|
27
29
|
updatedAt: string;
|
|
28
30
|
}
|
|
@@ -122,7 +124,7 @@ export interface SiteDeploy {
|
|
|
122
124
|
number: number;
|
|
123
125
|
/** uploading: files are being declared and sent. ready: every file is stored, and it can be made live. cancelled or expired: given up on, and it holds nothing. */
|
|
124
126
|
state: "uploading" | "ready" | "cancelled" | "expired";
|
|
125
|
-
/** upload: sent by
|
|
127
|
+
/** upload: sent from a computer, by the CLI or a program. folder: copied from a folder in the drive, on the website. */
|
|
126
128
|
source: "upload" | "folder";
|
|
127
129
|
fileCount: number;
|
|
128
130
|
/** What its files add up to. */
|
|
@@ -147,6 +149,36 @@ export interface SendTo {
|
|
|
147
149
|
/** When the address stops working. sites.sendAgain gives fresh ones. */
|
|
148
150
|
expiresAt: string;
|
|
149
151
|
}
|
|
152
|
+
/** A page of a protected file's map: its key, and where each fragment is. */
|
|
153
|
+
export interface ShardMap {
|
|
154
|
+
/** The content's own id, which each fragment's check is bound to with its place and the count. */
|
|
155
|
+
contentId: string;
|
|
156
|
+
/** The file's size. */
|
|
157
|
+
sizeBytes: number;
|
|
158
|
+
/** How many bytes of the file each fragment holds, except the last, which holds what remains. */
|
|
159
|
+
fragmentBytes: number;
|
|
160
|
+
/** How many fragments the file is. */
|
|
161
|
+
count: number;
|
|
162
|
+
/** The file's own key, in base64: 32 bytes, which open its fragments. In this answer and nowhere else. */
|
|
163
|
+
key: string;
|
|
164
|
+
name: string;
|
|
165
|
+
contentType: string | null;
|
|
166
|
+
/** The file's revision whose content this is. Its fragments never change, however late they are read. */
|
|
167
|
+
revision: number;
|
|
168
|
+
/** The first place on this page. */
|
|
169
|
+
from: number;
|
|
170
|
+
/** Up to 1000, in order of place. */
|
|
171
|
+
fragments: Array<{
|
|
172
|
+
/** Counted from zero. Its bytes of the file begin at place times fragmentBytes. */
|
|
173
|
+
place: number;
|
|
174
|
+
/** Where to fetch the stored fragment, with a plain GET and no key: the address is the permission. */
|
|
175
|
+
url: string;
|
|
176
|
+
}>;
|
|
177
|
+
/** The from of the next page, or null when this page reaches the last fragment. */
|
|
178
|
+
next: number | null;
|
|
179
|
+
/** When this page's addresses stop working. Ask for the page again before then, from the first fragment not yet fetched. */
|
|
180
|
+
expiresAt: string;
|
|
181
|
+
}
|
|
150
182
|
/** What GET /v1/files takes in its query. */
|
|
151
183
|
export type FilesListQuery = {
|
|
152
184
|
/** The folder to list. Left out, the top of the app (or of the folder the key is confined to). */
|
|
@@ -328,6 +360,13 @@ export type FilesDownloadUrlAnswer = {
|
|
|
328
360
|
inline: boolean;
|
|
329
361
|
contentType: string | null;
|
|
330
362
|
};
|
|
363
|
+
/** What GET /v1/files/:id/shards takes in its query. */
|
|
364
|
+
export type FilesShardsQuery = {
|
|
365
|
+
/** The first fragment wanted, counted from zero: 0, or the `next` of the page before. */
|
|
366
|
+
from?: number;
|
|
367
|
+
};
|
|
368
|
+
/** What GET /v1/files/:id/shards answers with. */
|
|
369
|
+
export type FilesShardsAnswer = ShardMap;
|
|
331
370
|
/** What GET /v1/files/:id/image takes in its query. */
|
|
332
371
|
export type FilesImageQuery = {
|
|
333
372
|
/** One of 64, 128, 256, 512, 1024. */
|
|
@@ -367,7 +406,7 @@ export type UsageGetAnswer = {
|
|
|
367
406
|
};
|
|
368
407
|
/** What GET /v1/me answers with. */
|
|
369
408
|
export type MeGetAnswer = {
|
|
370
|
-
/** key: an app's key, on a server. token: a token a key made for a web page. device: a person, signed in with
|
|
409
|
+
/** key: an app's key, on a server. token: a token a key made for a web page. device: a person, signed in with filefreak login. */
|
|
371
410
|
via: "key" | "token" | "device";
|
|
372
411
|
account: {
|
|
373
412
|
username: string;
|
|
@@ -621,6 +660,12 @@ export declare const OPERATIONS: {
|
|
|
621
660
|
readonly idempotent: false;
|
|
622
661
|
readonly repeatable: false;
|
|
623
662
|
};
|
|
663
|
+
readonly "files.shards": {
|
|
664
|
+
readonly method: "GET";
|
|
665
|
+
readonly path: "/v1/files/:id/shards";
|
|
666
|
+
readonly idempotent: false;
|
|
667
|
+
readonly repeatable: false;
|
|
668
|
+
};
|
|
624
669
|
readonly "files.image": {
|
|
625
670
|
readonly method: "GET";
|
|
626
671
|
readonly path: "/v1/files/:id/image";
|
|
@@ -780,11 +825,19 @@ export declare function bind(call: Call): {
|
|
|
780
825
|
/**
|
|
781
826
|
* An address to download a file from.
|
|
782
827
|
*
|
|
783
|
-
* 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 is answered with 409 shard_protected
|
|
828
|
+
* 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.
|
|
784
829
|
*
|
|
785
830
|
* GET /v1/files/:id/download. Needs the scope files:read.
|
|
786
831
|
*/
|
|
787
832
|
downloadUrl: (id: string, query?: FilesDownloadUrlQuery, options?: CallOptions) => Promise<FilesDownloadUrlAnswer>;
|
|
833
|
+
/**
|
|
834
|
+
* A protected file's map.
|
|
835
|
+
*
|
|
836
|
+
* 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.
|
|
837
|
+
*
|
|
838
|
+
* GET /v1/files/:id/shards. Needs the scope files:read.
|
|
839
|
+
*/
|
|
840
|
+
shards: (id: string, query?: FilesShardsQuery, options?: CallOptions) => Promise<FilesShardsAnswer>;
|
|
788
841
|
/**
|
|
789
842
|
* An image at a smaller size.
|
|
790
843
|
*
|
|
@@ -836,6 +889,8 @@ export declare function bind(call: Call): {
|
|
|
836
889
|
*
|
|
837
890
|
* 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.
|
|
838
891
|
*
|
|
892
|
+
* 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.
|
|
893
|
+
*
|
|
839
894
|
* POST /v1/uploads. Needs the scope files:write. Honours an Idempotency-Key.
|
|
840
895
|
*/
|
|
841
896
|
begin: (body: UploadsBeginBody, options?: CallOptions) => Promise<UploadsBeginAnswer>;
|
|
@@ -876,7 +931,7 @@ export declare function bind(call: Call): {
|
|
|
876
931
|
/**
|
|
877
932
|
* What the app is using.
|
|
878
933
|
*
|
|
879
|
-
* 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
|
|
934
|
+
* 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.
|
|
880
935
|
*
|
|
881
936
|
* GET /v1/usage. Needs the scope usage:read.
|
|
882
937
|
*/
|
|
@@ -886,7 +941,7 @@ export declare function bind(call: Call): {
|
|
|
886
941
|
/**
|
|
887
942
|
* Who this is.
|
|
888
943
|
*
|
|
889
|
-
* 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
|
|
944
|
+
* 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.
|
|
890
945
|
*
|
|
891
946
|
* GET /v1/me. Any key may call it.
|
|
892
947
|
*/
|
|
@@ -896,25 +951,25 @@ export declare function bind(call: Call): {
|
|
|
896
951
|
/**
|
|
897
952
|
* Make a share link.
|
|
898
953
|
*
|
|
899
|
-
* 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
|
|
954
|
+
* 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.
|
|
900
955
|
*
|
|
901
|
-
* POST /v1/shares. Only a device signed in with
|
|
956
|
+
* POST /v1/shares. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
902
957
|
*/
|
|
903
958
|
create: (body: SharesCreateBody, options?: CallOptions) => Promise<SharesCreateAnswer>;
|
|
904
959
|
/**
|
|
905
960
|
* List share links.
|
|
906
961
|
*
|
|
907
|
-
* 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
|
|
962
|
+
* 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.
|
|
908
963
|
*
|
|
909
|
-
* GET /v1/shares. Only a device signed in with
|
|
964
|
+
* GET /v1/shares. Only a device signed in with filefreak login may call it.
|
|
910
965
|
*/
|
|
911
966
|
list: (query?: SharesListQuery, options?: CallOptions) => Promise<SharesListAnswer>;
|
|
912
967
|
/**
|
|
913
968
|
* Remove a share link.
|
|
914
969
|
*
|
|
915
|
-
* It stops working with the next request, and cannot be brought back. Only a device signed in with
|
|
970
|
+
* It stops working with the next request, and cannot be brought back. Only a device signed in with filefreak login.
|
|
916
971
|
*
|
|
917
|
-
* DELETE /v1/shares/:id. Only a device signed in with
|
|
972
|
+
* DELETE /v1/shares/:id. Only a device signed in with filefreak login may call it.
|
|
918
973
|
*/
|
|
919
974
|
revoke: (id: string, options?: CallOptions) => Promise<SharesRevokeAnswer>;
|
|
920
975
|
};
|
|
@@ -922,9 +977,9 @@ export declare function bind(call: Call): {
|
|
|
922
977
|
/**
|
|
923
978
|
* List sites.
|
|
924
979
|
*
|
|
925
|
-
* 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
|
|
980
|
+
* 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.
|
|
926
981
|
*
|
|
927
|
-
* GET /v1/sites. Only a device signed in with
|
|
982
|
+
* GET /v1/sites. Only a device signed in with filefreak login may call it.
|
|
928
983
|
*/
|
|
929
984
|
list: (options?: CallOptions) => Promise<SitesListAnswer>;
|
|
930
985
|
/**
|
|
@@ -932,7 +987,7 @@ export declare function bind(call: Call): {
|
|
|
932
987
|
*
|
|
933
988
|
* 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.
|
|
934
989
|
*
|
|
935
|
-
* POST /v1/sites. Only a device signed in with
|
|
990
|
+
* POST /v1/sites. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
936
991
|
*/
|
|
937
992
|
create: (body: SitesCreateBody, options?: CallOptions) => Promise<SitesCreateAnswer>;
|
|
938
993
|
/**
|
|
@@ -940,7 +995,7 @@ export declare function bind(call: Call): {
|
|
|
940
995
|
*
|
|
941
996
|
* A site, and its deploys newest first. A site keeps its 10 newest deploys that have ended besides the live one.
|
|
942
997
|
*
|
|
943
|
-
* GET /v1/sites/:id. Only a device signed in with
|
|
998
|
+
* GET /v1/sites/:id. Only a device signed in with filefreak login may call it.
|
|
944
999
|
*/
|
|
945
1000
|
get: (id: string, options?: CallOptions) => Promise<SitesGetAnswer>;
|
|
946
1001
|
/**
|
|
@@ -948,7 +1003,7 @@ export declare function bind(call: Call): {
|
|
|
948
1003
|
*
|
|
949
1004
|
* 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.
|
|
950
1005
|
*
|
|
951
|
-
* POST /v1/sites/:id/deploys. Only a device signed in with
|
|
1006
|
+
* POST /v1/sites/:id/deploys. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
952
1007
|
*/
|
|
953
1008
|
startDeploy: (id: string, body: SitesStartDeployBody, options?: CallOptions) => Promise<SitesStartDeployAnswer>;
|
|
954
1009
|
/**
|
|
@@ -956,7 +1011,7 @@ export declare function bind(call: Call): {
|
|
|
956
1011
|
*
|
|
957
1012
|
* The next 1000 files of a deploy at most, as sites.startDeploy takes them. A path declared twice is refused (path_declared_twice).
|
|
958
1013
|
*
|
|
959
|
-
* POST /v1/sites/deploys/:id/files. Only a device signed in with
|
|
1014
|
+
* POST /v1/sites/deploys/:id/files. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
960
1015
|
*/
|
|
961
1016
|
declareFiles: (id: string, body: SitesDeclareFilesBody, options?: CallOptions) => Promise<SitesDeclareFilesAnswer>;
|
|
962
1017
|
/**
|
|
@@ -964,7 +1019,7 @@ export declare function bind(call: Call): {
|
|
|
964
1019
|
*
|
|
965
1020
|
* 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.
|
|
966
1021
|
*
|
|
967
|
-
* POST /v1/sites/deploys/:id/send. Only a device signed in with
|
|
1022
|
+
* POST /v1/sites/deploys/:id/send. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
968
1023
|
*/
|
|
969
1024
|
sendAgain: (id: string, body: SitesSendAgainBody, options?: CallOptions) => Promise<SitesSendAgainAnswer>;
|
|
970
1025
|
/**
|
|
@@ -972,7 +1027,7 @@ export declare function bind(call: Call): {
|
|
|
972
1027
|
*
|
|
973
1028
|
* 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.
|
|
974
1029
|
*
|
|
975
|
-
* POST /v1/sites/deploys/:id/finish. Only a device signed in with
|
|
1030
|
+
* POST /v1/sites/deploys/:id/finish. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
976
1031
|
*/
|
|
977
1032
|
finishDeploy: (id: string, body?: SitesFinishDeployBody, options?: CallOptions) => Promise<SitesFinishDeployAnswer>;
|
|
978
1033
|
/**
|
|
@@ -980,7 +1035,7 @@ export declare function bind(call: Call): {
|
|
|
980
1035
|
*
|
|
981
1036
|
* 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).
|
|
982
1037
|
*
|
|
983
|
-
* DELETE /v1/sites/deploys/:id. Only a device signed in with
|
|
1038
|
+
* DELETE /v1/sites/deploys/:id. Only a device signed in with filefreak login may call it.
|
|
984
1039
|
*/
|
|
985
1040
|
removeDeploy: (id: string, options?: CallOptions) => Promise<SitesRemoveDeployAnswer>;
|
|
986
1041
|
/**
|
|
@@ -988,7 +1043,7 @@ export declare function bind(call: Call): {
|
|
|
988
1043
|
*
|
|
989
1044
|
* 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.
|
|
990
1045
|
*
|
|
991
|
-
* POST /v1/sites/:id/live. Only a device signed in with
|
|
1046
|
+
* POST /v1/sites/:id/live. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
992
1047
|
*/
|
|
993
1048
|
setLive: (id: string, body: SitesSetLiveBody, options?: CallOptions) => Promise<SitesSetLiveAnswer>;
|
|
994
1049
|
};
|
package/dist/generated.js
CHANGED
|
@@ -20,6 +20,7 @@ export const OPERATIONS = {
|
|
|
20
20
|
"uploads.complete": { method: "POST", path: "/v1/uploads/:id/complete", idempotent: false, repeatable: true },
|
|
21
21
|
"uploads.cancel": { method: "DELETE", path: "/v1/uploads/:id", idempotent: false, repeatable: false },
|
|
22
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 },
|
|
23
24
|
"files.image": { method: "GET", path: "/v1/files/:id/image", idempotent: false, repeatable: false },
|
|
24
25
|
"usage.get": { method: "GET", path: "/v1/usage", idempotent: false, repeatable: false },
|
|
25
26
|
"me.get": { method: "GET", path: "/v1/me", idempotent: false, repeatable: false },
|
|
@@ -92,11 +93,19 @@ export function bind(call) {
|
|
|
92
93
|
/**
|
|
93
94
|
* An address to download a file from.
|
|
94
95
|
*
|
|
95
|
-
* 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 is answered with 409 shard_protected
|
|
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.
|
|
96
97
|
*
|
|
97
98
|
* GET /v1/files/:id/download. Needs the scope files:read.
|
|
98
99
|
*/
|
|
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),
|
|
100
109
|
/**
|
|
101
110
|
* An image at a smaller size.
|
|
102
111
|
*
|
|
@@ -148,6 +157,8 @@ export function bind(call) {
|
|
|
148
157
|
*
|
|
149
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.
|
|
150
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
|
+
*
|
|
151
162
|
* POST /v1/uploads. Needs the scope files:write. Honours an Idempotency-Key.
|
|
152
163
|
*/
|
|
153
164
|
begin: (body, options) => call("uploads.begin", { body }, options),
|
|
@@ -188,7 +199,7 @@ export function bind(call) {
|
|
|
188
199
|
/**
|
|
189
200
|
* What the app is using.
|
|
190
201
|
*
|
|
191
|
-
* 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
|
|
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.
|
|
192
203
|
*
|
|
193
204
|
* GET /v1/usage. Needs the scope usage:read.
|
|
194
205
|
*/
|
|
@@ -198,7 +209,7 @@ export function bind(call) {
|
|
|
198
209
|
/**
|
|
199
210
|
* Who this is.
|
|
200
211
|
*
|
|
201
|
-
* 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
|
|
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.
|
|
202
213
|
*
|
|
203
214
|
* GET /v1/me. Any key may call it.
|
|
204
215
|
*/
|
|
@@ -208,25 +219,25 @@ export function bind(call) {
|
|
|
208
219
|
/**
|
|
209
220
|
* Make a share link.
|
|
210
221
|
*
|
|
211
|
-
* 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
|
|
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.
|
|
212
223
|
*
|
|
213
|
-
* POST /v1/shares. Only a device signed in with
|
|
224
|
+
* POST /v1/shares. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
214
225
|
*/
|
|
215
226
|
create: (body, options) => call("shares.create", { body }, options),
|
|
216
227
|
/**
|
|
217
228
|
* List share links.
|
|
218
229
|
*
|
|
219
|
-
* 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
|
|
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.
|
|
220
231
|
*
|
|
221
|
-
* GET /v1/shares. Only a device signed in with
|
|
232
|
+
* GET /v1/shares. Only a device signed in with filefreak login may call it.
|
|
222
233
|
*/
|
|
223
234
|
list: (query, options) => call("shares.list", { query }, options),
|
|
224
235
|
/**
|
|
225
236
|
* Remove a share link.
|
|
226
237
|
*
|
|
227
|
-
* It stops working with the next request, and cannot be brought back. Only a device signed in with
|
|
238
|
+
* It stops working with the next request, and cannot be brought back. Only a device signed in with filefreak login.
|
|
228
239
|
*
|
|
229
|
-
* DELETE /v1/shares/:id. Only a device signed in with
|
|
240
|
+
* DELETE /v1/shares/:id. Only a device signed in with filefreak login may call it.
|
|
230
241
|
*/
|
|
231
242
|
revoke: (id, options) => call("shares.revoke", { params: { id } }, options),
|
|
232
243
|
},
|
|
@@ -234,9 +245,9 @@ export function bind(call) {
|
|
|
234
245
|
/**
|
|
235
246
|
* List sites.
|
|
236
247
|
*
|
|
237
|
-
* 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
|
|
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.
|
|
238
249
|
*
|
|
239
|
-
* GET /v1/sites. Only a device signed in with
|
|
250
|
+
* GET /v1/sites. Only a device signed in with filefreak login may call it.
|
|
240
251
|
*/
|
|
241
252
|
list: (options) => call("sites.list", {}, options),
|
|
242
253
|
/**
|
|
@@ -244,7 +255,7 @@ export function bind(call) {
|
|
|
244
255
|
*
|
|
245
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.
|
|
246
257
|
*
|
|
247
|
-
* POST /v1/sites. Only a device signed in with
|
|
258
|
+
* POST /v1/sites. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
248
259
|
*/
|
|
249
260
|
create: (body, options) => call("sites.create", { body }, options),
|
|
250
261
|
/**
|
|
@@ -252,7 +263,7 @@ export function bind(call) {
|
|
|
252
263
|
*
|
|
253
264
|
* A site, and its deploys newest first. A site keeps its 10 newest deploys that have ended besides the live one.
|
|
254
265
|
*
|
|
255
|
-
* GET /v1/sites/:id. Only a device signed in with
|
|
266
|
+
* GET /v1/sites/:id. Only a device signed in with filefreak login may call it.
|
|
256
267
|
*/
|
|
257
268
|
get: (id, options) => call("sites.get", { params: { id } }, options),
|
|
258
269
|
/**
|
|
@@ -260,7 +271,7 @@ export function bind(call) {
|
|
|
260
271
|
*
|
|
261
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.
|
|
262
273
|
*
|
|
263
|
-
* POST /v1/sites/:id/deploys. Only a device signed in with
|
|
274
|
+
* POST /v1/sites/:id/deploys. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
264
275
|
*/
|
|
265
276
|
startDeploy: (id, body, options) => call("sites.startDeploy", { params: { id }, body }, options),
|
|
266
277
|
/**
|
|
@@ -268,7 +279,7 @@ export function bind(call) {
|
|
|
268
279
|
*
|
|
269
280
|
* The next 1000 files of a deploy at most, as sites.startDeploy takes them. A path declared twice is refused (path_declared_twice).
|
|
270
281
|
*
|
|
271
|
-
* POST /v1/sites/deploys/:id/files. Only a device signed in with
|
|
282
|
+
* POST /v1/sites/deploys/:id/files. Only a device signed in with filefreak login may call it. Honours an Idempotency-Key.
|
|
272
283
|
*/
|
|
273
284
|
declareFiles: (id, body, options) => call("sites.declareFiles", { params: { id }, body }, options),
|
|
274
285
|
/**
|
|
@@ -276,7 +287,7 @@ export function bind(call) {
|
|
|
276
287
|
*
|
|
277
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.
|
|
278
289
|
*
|
|
279
|
-
* POST /v1/sites/deploys/:id/send. Only a device signed in with
|
|
290
|
+
* POST /v1/sites/deploys/:id/send. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
280
291
|
*/
|
|
281
292
|
sendAgain: (id, body, options) => call("sites.sendAgain", { params: { id }, body }, options),
|
|
282
293
|
/**
|
|
@@ -284,7 +295,7 @@ export function bind(call) {
|
|
|
284
295
|
*
|
|
285
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.
|
|
286
297
|
*
|
|
287
|
-
* POST /v1/sites/deploys/:id/finish. Only a device signed in with
|
|
298
|
+
* POST /v1/sites/deploys/:id/finish. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
288
299
|
*/
|
|
289
300
|
finishDeploy: (id, body, options) => call("sites.finishDeploy", { params: { id }, body }, options),
|
|
290
301
|
/**
|
|
@@ -292,7 +303,7 @@ export function bind(call) {
|
|
|
292
303
|
*
|
|
293
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).
|
|
294
305
|
*
|
|
295
|
-
* DELETE /v1/sites/deploys/:id. Only a device signed in with
|
|
306
|
+
* DELETE /v1/sites/deploys/:id. Only a device signed in with filefreak login may call it.
|
|
296
307
|
*/
|
|
297
308
|
removeDeploy: (id, options) => call("sites.removeDeploy", { params: { id } }, options),
|
|
298
309
|
/**
|
|
@@ -300,7 +311,7 @@ export function bind(call) {
|
|
|
300
311
|
*
|
|
301
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.
|
|
302
313
|
*
|
|
303
|
-
* POST /v1/sites/:id/live. Only a device signed in with
|
|
314
|
+
* POST /v1/sites/:id/live. Only a device signed in with filefreak login may call it. Safe to send again.
|
|
304
315
|
*/
|
|
305
316
|
setLive: (id, body, options) => call("sites.setLive", { params: { id }, body }, options),
|
|
306
317
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { FileFreak, Walk, type DownloadOptions, type FollowOptions } from "./client.js";
|
|
2
2
|
export * from "./generated.js";
|
|
3
|
+
export { get, type GetOptions, type Got, type Into, type LinkedFile } from "./links.js";
|
|
3
4
|
export { type Sink } from "./ranges.js";
|
|
4
5
|
export { openFragment, sealFragment, SHARD_OVERHEAD, SHARD_VERSION, ShardError, shardKey, ShardLayout, type FragmentAt, type ShardErrorCode, type ShardKey, } from "./shards.js";
|
|
5
6
|
export { FileFreakError, type CallOptions, type ClientOptions, type TokenSource } from "./transport.js";
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
//
|
|
6
6
|
// In a web page, give it a token the page's own server made with its key
|
|
7
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"));
|
|
8
12
|
export { FileFreak, Walk } from "./client.js";
|
|
9
13
|
export * from "./generated.js";
|
|
14
|
+
export { get } from "./links.js";
|
|
10
15
|
export { openFragment, sealFragment, SHARD_OVERHEAD, SHARD_VERSION, ShardError, shardKey, ShardLayout, } from "./shards.js";
|
|
11
16
|
export { FileFreakError } from "./transport.js";
|
|
12
17
|
export { UploadStopped } from "./uploads.js";
|