notefeed 0.8.0 → 0.9.1
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 +3 -3
- package/dist/cli.js +8 -11
- package/dist/client.d.ts +7 -8
- package/dist/client.js +31 -56
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/sdk.gen.d.ts +3 -3
- package/dist/generated/sdk.gen.js +3 -3
- package/dist/generated/types.gen.d.ts +126 -20
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# notefeed
|
|
2
2
|
|
|
3
|
-
Post and read markdown notes on a [notefeed](https://github.com/
|
|
3
|
+
Post and read markdown notes on a [notefeed](https://github.com/notefeed/notefeed) server from Node or the command line. No dependencies; Node 20 or newer.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm install notefeed
|
|
@@ -31,6 +31,6 @@ A posted note can be changed or removed: `await client.edit(id, content)` replac
|
|
|
31
31
|
|
|
32
32
|
A feed can have a title and a description, and can be deleted: `await client.feedInfo()` returns `{ name, title, description, protected, read_url }`, `await client.updateFeed({ title, description })` replaces both (an empty string clears one) and returns the feed, and `await client.deleteFeed()` removes the feed with all its notes for good. All three take the same `{ feed, feedPassword }` options as `post`, and a feed that doesn't exist is a `NotFoundError`. Anyone who can post to a feed can do this, and deleting is permanent; there are no `notefeed` commands for it.
|
|
33
33
|
|
|
34
|
-
A picture is a note of its own: `await client.post(bytes, { type: "image/png", alt: "…" })` takes a `Uint8Array` or a `Blob` (PNG, JPEG, GIF or WebP; a Blob's own type is used if you leave `type` out) and returns what a markdown post returns, with the picture's `file` and `file_url` added. Write `` in a markdown note to show it; the feed is created by its first note, and a picture that is too large is a `NoteTooLargeError`. The server checks the bytes against the declared type. `await client.update(id, { title, alt })` changes a note's title or a picture's alt text, and `await client.edit(id, content)` replaces its content. `await client.updateFeed({ title, description, image: file })` makes a picture the feed's title image (`image: ""` removes it; leaving `image` out keeps it). `notefeed post --file photo.png` posts a file (the type comes from the extension, or `--type`). To post a note with its pictures in one call, `await client.post(text, { attachments: [{ name: "chart.png", content: bytes, type: "image/png" }] })` posts them
|
|
34
|
+
A picture is a note of its own: `await client.post(bytes, { type: "image/png", alt: "…" })` takes a `Uint8Array` or a `Blob` (PNG, JPEG, GIF or WebP; a Blob's own type is used if you leave `type` out) and returns what a markdown post returns, with the picture's `file` and `file_url` added. Write `` in a markdown note to show it; the feed is created by its first note, and a picture that is too large is a `NoteTooLargeError`. The server checks the bytes against the declared type. `await client.update(id, { title, alt })` changes a note's title or a picture's alt text, and `await client.edit(id, content)` replaces its content. `await client.updateFeed({ title, description, image: file })` makes a picture the feed's title image (`image: ""` removes it; leaving `image` out keeps it). `notefeed post --file photo.png` posts a file (the type comes from the extension, or `--type`). To post a note with its pictures in one call, `await client.post(text, { attachments: [{ name: "chart.png", content: bytes, type: "image/png" }] })` posts them with the text in one request, and the server swaps `` for each file name (`null` content posts only the pictures) (`notefeed post "…" --attach chart.png` does the same); nothing is posted when one is refused. Pictures are public to anyone with the feed's read link, and metadata such as EXIF is not removed.
|
|
35
35
|
|
|
36
|
-
Full documentation: https://docs.notefeed.me/clients/
|
|
36
|
+
Full documentation: https://docs.notefeed.me/integrations/clients/
|
package/dist/cli.js
CHANGED
|
@@ -48,10 +48,13 @@ export async function main(argv, io = process) {
|
|
|
48
48
|
}
|
|
49
49
|
const [command, text, ...rest] = positionals;
|
|
50
50
|
if (command === "post" && !rest.length) {
|
|
51
|
-
const input = await read(text, values.file, values.type, io);
|
|
52
51
|
const attachments = await Promise.all((values.attach ?? []).map(attachment));
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
// Pictures alone need no text; the result is then the first picture, whose URL is also in `attachments`.
|
|
53
|
+
const noText = attachments.length > 0 && text === undefined && !values.file;
|
|
54
|
+
const input = noText ? { content: null, type: undefined, name: undefined } : await read(text, values.file, values.type, io);
|
|
55
|
+
// The server refuses a file name next to attachments: the text has none then.
|
|
56
|
+
const note = await client(values).post(input.content, { type: input.type, title: values.title, tags: values.tag, name: attachments.length ? undefined : input.name, attachments });
|
|
57
|
+
io.stdout.write(`${[...(noText ? [] : [note.url]), ...note.attachments.map((a) => a.url)].join("\n")}\n`);
|
|
55
58
|
return 0;
|
|
56
59
|
}
|
|
57
60
|
if (command === "edit" && text !== undefined && rest.length <= 1) {
|
|
@@ -91,9 +94,6 @@ export async function main(argv, io = process) {
|
|
|
91
94
|
}
|
|
92
95
|
catch (e) {
|
|
93
96
|
io.stderr.write(`notefeed: ${e.message.split("\n")[0]}\n`);
|
|
94
|
-
if (e instanceof NotefeedError)
|
|
95
|
-
for (const p of e.posted)
|
|
96
|
-
io.stderr.write(`posted: ${p.url}\n`);
|
|
97
97
|
if (e instanceof ConfigError || e instanceof UsageError)
|
|
98
98
|
return 2;
|
|
99
99
|
if (e instanceof NotefeedError)
|
|
@@ -141,16 +141,13 @@ async function read(text, file, type, io) {
|
|
|
141
141
|
throw new UsageError('give the note text, "-" for stdin, or --file PATH');
|
|
142
142
|
return { content: text, type: type ?? "text/markdown" };
|
|
143
143
|
}
|
|
144
|
-
// A picture to post
|
|
144
|
+
// A picture to post with the note: its name is the file's (the client checks it), its type comes from the extension.
|
|
145
145
|
async function attachment(path) {
|
|
146
146
|
const type = TYPES[extname(path).toLowerCase()];
|
|
147
147
|
if (!type || type === "text/markdown")
|
|
148
148
|
throw new UsageError(`cannot attach ${path}: a picture (${Object.keys(TYPES).filter((e) => TYPES[e] !== "text/markdown").join(", ")}) is expected`);
|
|
149
|
-
const name = basename(path);
|
|
150
|
-
if (!/^(?!\.+$)[A-Za-z0-9._-]+$/.test(name))
|
|
151
|
-
throw new UsageError(`cannot attach ${path}: its file name "${name}" is what the text refers to it by, so it may only have letters, digits, ., _ and -: rename the file`);
|
|
152
149
|
try {
|
|
153
|
-
return { name, content: await readFile(path), type };
|
|
150
|
+
return { name: basename(path), content: await readFile(path), type };
|
|
154
151
|
}
|
|
155
152
|
catch (e) {
|
|
156
153
|
throw new UsageError(`cannot read ${path}: ${e.code ?? e.message}`);
|
package/dist/client.d.ts
CHANGED
|
@@ -22,9 +22,6 @@ export declare class NotefeedError extends Error {
|
|
|
22
22
|
readonly status: number | null;
|
|
23
23
|
readonly code: ErrorCode | null;
|
|
24
24
|
constructor(message: string, status?: number | null, code?: ErrorCode | null);
|
|
25
|
-
/** Set when a post with `attachments` failed on one of them: its name, and the images already posted (the text note is not). */
|
|
26
|
-
attachment: string | null;
|
|
27
|
-
posted: Created[];
|
|
28
25
|
}
|
|
29
26
|
/** Raised before sending: no URL, no feed, an invalid feed name or password. */
|
|
30
27
|
export declare class ConfigError extends NotefeedError {
|
|
@@ -70,12 +67,14 @@ export declare class Client {
|
|
|
70
67
|
* text. `alt` is a picture's alternative text, `name` the file's original name. `readId` is the read id the feed gets when this post creates it
|
|
71
68
|
* (3 to 64 characters of `a-z`, `0-9`, `-`, `_`; random when left out; ignored for a feed that exists; a `taken` error when another feed has it).
|
|
72
69
|
*
|
|
73
|
-
* `attachments`
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
70
|
+
* `attachments` are pictures posted with the note in one request: `` in the markdown shows one (a picture the text never refers to is
|
|
71
|
+
* added at the end), and `Created.attachments` lists them in order. `tags` label the pictures too. `content` may be `null` when there are
|
|
72
|
+
* attachments: only the pictures are posted, `title` and `tags` go on each, and the result is the first picture plus `attachments`. Checked
|
|
73
|
+
* here, before anything is sent (ConfigError): a name given twice, an attachment that is not a picture, content that is not markdown, `alt` or
|
|
74
|
+
* `name` with attachments. What a name may be is the server's rule (docs/using/pictures.md, "Posting a note with its pictures"): a name it refuses is an
|
|
75
|
+
* InvalidRequestError, `attachment "<name>": ...`, and whenever the server refuses any part (its message names it) nothing is posted.
|
|
77
76
|
*/
|
|
78
|
-
post(content: string | Uint8Array | Blob, options?: {
|
|
77
|
+
post(content: string | Uint8Array | Blob | null, options?: {
|
|
79
78
|
feed?: string;
|
|
80
79
|
feedPassword?: string;
|
|
81
80
|
type?: string;
|
package/dist/client.js
CHANGED
|
@@ -14,9 +14,6 @@ export class NotefeedError extends Error {
|
|
|
14
14
|
this.code = code;
|
|
15
15
|
this.name = new.target.name;
|
|
16
16
|
}
|
|
17
|
-
/** Set when a post with `attachments` failed on one of them: its name, and the images already posted (the text note is not). */
|
|
18
|
-
attachment = null;
|
|
19
|
-
posted = [];
|
|
20
17
|
}
|
|
21
18
|
/** Raised before sending: no URL, no feed, an invalid feed name or password. */
|
|
22
19
|
export class ConfigError extends NotefeedError {
|
|
@@ -60,7 +57,6 @@ const BY_CODE = {
|
|
|
60
57
|
taken: InvalidRequestError,
|
|
61
58
|
unsupported_type: InvalidRequestError,
|
|
62
59
|
};
|
|
63
|
-
const ATTACHMENT_NAME = /^(?!\.+$)[A-Za-z0-9._-]+$/; // same rule as the server's MCP tool: safe to write in 
|
|
64
60
|
const IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
65
61
|
const FEED_RE = /^[a-z0-9_-]{1,64}$/; // same rule as the server; reserved names still come back as a 400
|
|
66
62
|
// A header holds bytes, and fetch refuses a character above U+00FF: text that may not be ASCII goes as its UTF-8 bytes written as
|
|
@@ -75,18 +71,6 @@ function asFile(content, type) {
|
|
|
75
71
|
throw new ConfigError("give the file's media type as `type`, e.g. image/png");
|
|
76
72
|
return { body: content instanceof Blob ? content : new Blob([content]), type: media };
|
|
77
73
|
}
|
|
78
|
-
// The markdown with each `` of `sent` (name → file) pointing at its file; a name the text never refers to is appended as ``.
|
|
79
|
-
function placeImages(markdown, sent) {
|
|
80
|
-
const used = new Set();
|
|
81
|
-
const text = markdown.replace(/(!\[[^\]]*\]\()([^)\s]+)(\))/g, (m, head, dest, tail) => {
|
|
82
|
-
if (!sent.has(dest))
|
|
83
|
-
return m;
|
|
84
|
-
used.add(dest);
|
|
85
|
-
return head + sent.get(dest) + tail;
|
|
86
|
-
});
|
|
87
|
-
const rest = [...sent].filter(([name]) => !used.has(name)).map(([, file]) => ``);
|
|
88
|
-
return rest.length === 0 ? text : [text.trimEnd(), ...rest].filter((p) => p !== "").join("\n\n");
|
|
89
|
-
}
|
|
90
74
|
export class Client {
|
|
91
75
|
url;
|
|
92
76
|
feed;
|
|
@@ -128,55 +112,46 @@ export class Client {
|
|
|
128
112
|
* text. `alt` is a picture's alternative text, `name` the file's original name. `readId` is the read id the feed gets when this post creates it
|
|
129
113
|
* (3 to 64 characters of `a-z`, `0-9`, `-`, `_`; random when left out; ignored for a feed that exists; a `taken` error when another feed has it).
|
|
130
114
|
*
|
|
131
|
-
* `attachments`
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
115
|
+
* `attachments` are pictures posted with the note in one request: `` in the markdown shows one (a picture the text never refers to is
|
|
116
|
+
* added at the end), and `Created.attachments` lists them in order. `tags` label the pictures too. `content` may be `null` when there are
|
|
117
|
+
* attachments: only the pictures are posted, `title` and `tags` go on each, and the result is the first picture plus `attachments`. Checked
|
|
118
|
+
* here, before anything is sent (ConfigError): a name given twice, an attachment that is not a picture, content that is not markdown, `alt` or
|
|
119
|
+
* `name` with attachments. What a name may be is the server's rule (docs/using/pictures.md, "Posting a note with its pictures"): a name it refuses is an
|
|
120
|
+
* InvalidRequestError, `attachment "<name>": ...`, and whenever the server refuses any part (its message names it) nothing is posted.
|
|
135
121
|
*/
|
|
136
122
|
async post(content, options = {}) {
|
|
137
123
|
const { attachments = [], ...own } = options;
|
|
124
|
+
if (content === null && attachments.length === 0)
|
|
125
|
+
throw new ConfigError("no content and no attachments");
|
|
138
126
|
if (attachments.length === 0)
|
|
139
127
|
return { ...(await this.postOne(content, own)), attachments: [] };
|
|
140
|
-
if (typeof content !== "string")
|
|
141
|
-
throw new ConfigError("attachments go with a markdown string");
|
|
142
|
-
if ((own.type ?? "text/markdown") !== "text/markdown")
|
|
128
|
+
if (content !== null && (typeof content !== "string" || (own.type ?? "text/markdown") !== "text/markdown"))
|
|
143
129
|
throw new ConfigError("attachments go with a markdown string");
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
130
|
+
if (own.alt || own.name)
|
|
131
|
+
throw new ConfigError("alt and name do not go with attachments: give each attachment its alt");
|
|
132
|
+
const form = new FormData();
|
|
133
|
+
if (content !== null)
|
|
134
|
+
form.append("text", new Blob([content], { type: "text/markdown" }));
|
|
135
|
+
for (const a of attachments) {
|
|
136
|
+
if (attachments.findIndex((b) => b.name === a.name) !== attachments.indexOf(a))
|
|
137
|
+
throw new ConfigError(`attachment "${a.name}" is given twice`);
|
|
138
|
+
const { body, type } = asFile(a.content, a.type);
|
|
148
139
|
if (!IMAGE_TYPES.includes(type))
|
|
149
140
|
throw new ConfigError(`attachment "${a.name}" must be a picture (${IMAGE_TYPES.join(", ")})`);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (dup)
|
|
154
|
-
throw new ConfigError(`attachment "${dup.name}" is given twice`);
|
|
155
|
-
const posted = [];
|
|
156
|
-
const sent = new Map();
|
|
157
|
-
for (const [i, a] of attachments.entries()) {
|
|
158
|
-
try {
|
|
159
|
-
const done = await this.postOne(a.content, { feed: own.feed, feedPassword: own.feedPassword, type: types[i], alt: a.alt, name: a.name, tags: own.tags, readId: own.readId });
|
|
160
|
-
posted.push(done);
|
|
161
|
-
sent.set(a.name, done.file);
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
if (e instanceof NotefeedError) {
|
|
165
|
-
e.message = `attachment "${a.name}": ${e.message}`;
|
|
166
|
-
e.attachment = a.name;
|
|
167
|
-
e.posted = posted;
|
|
168
|
-
}
|
|
169
|
-
throw e;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
try {
|
|
173
|
-
return { ...(await this.postOne(placeImages(content, sent), own)), attachments: posted };
|
|
174
|
-
}
|
|
175
|
-
catch (e) {
|
|
176
|
-
if (e instanceof NotefeedError)
|
|
177
|
-
e.posted = posted; // the text failed: the images stay, `attachment` stays null
|
|
178
|
-
throw e;
|
|
141
|
+
form.append("file", new Blob([body], { type }), a.name);
|
|
142
|
+
if (a.alt)
|
|
143
|
+
form.append(`alt.${a.name}`, a.alt);
|
|
179
144
|
}
|
|
145
|
+
const feed = this.feedFor(own.feed);
|
|
146
|
+
const headers = {
|
|
147
|
+
...this.opts(own.feedPassword).headers,
|
|
148
|
+
"Content-Type": null, // fetch sets multipart/form-data with its boundary
|
|
149
|
+
...(own.title && { "X-Note-Title": headerValue(own.title) }),
|
|
150
|
+
...(own.tags?.length && { "X-Note-Tags": own.tags.join(",") }),
|
|
151
|
+
...(own.readId && { "X-Read-Id": own.readId }),
|
|
152
|
+
};
|
|
153
|
+
const created = await this.call(postNote({ client: this.api, path: { feed }, body: form, headers, signal: AbortSignal.timeout(this.timeoutMs) }));
|
|
154
|
+
return { ...created, attachments: created.attachments ?? [] };
|
|
180
155
|
}
|
|
181
156
|
async postOne(content, options) {
|
|
182
157
|
const feed = this.feedFor(options.feed);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { changeFeedPassword, deleteFeed, deleteNote, editNote, getFeed, getNote, getOpenApi, getReadFeed, getReadNote, listNotes, listReadNotes, type Options, patchNote, postNote, removeFeedPassword, updateFeed } from './sdk.gen.js';
|
|
2
|
-
export type { ChangeFeedPasswordData, ChangeFeedPasswordError, ChangeFeedPasswordErrors, ChangeFeedPasswordResponse, ChangeFeedPasswordResponses, ClientOptions, Created, DeleteFeedData, DeleteFeedError, DeleteFeedErrors, DeleteFeedResponse, DeleteFeedResponses, DeleteNoteData, DeleteNoteError, DeleteNoteErrors, DeleteNoteResponse, DeleteNoteResponses, EditNoteData, EditNoteError, EditNoteErrors, EditNoteResponse, EditNoteResponses, Error, Feed, FeedSettings, GetFeedData, GetFeedError, GetFeedErrors, GetFeedResponse, GetFeedResponses, GetNoteData, GetNoteError, GetNoteErrors, GetNoteResponse, GetNoteResponses, GetOpenApiData, GetOpenApiResponse, GetOpenApiResponses, GetReadFeedData, GetReadFeedError, GetReadFeedErrors, GetReadFeedResponse, GetReadFeedResponses, GetReadNoteData, GetReadNoteError, GetReadNoteErrors, GetReadNoteResponse, GetReadNoteResponses, ListNotesData, ListNotesError, ListNotesErrors, ListNotesResponse, ListNotesResponses, ListReadNotesData, ListReadNotesError, ListReadNotesErrors, ListReadNotesResponse, ListReadNotesResponses, Note, NoteList, NoteMeta, PasswordJson, PatchNoteData, PatchNoteError, PatchNoteErrors, PatchNoteResponse, PatchNoteResponses, PostNoteData, PostNoteError, PostNoteErrors, PostNoteResponse, PostNoteResponses, ReadFeed, RemoveFeedPasswordData, RemoveFeedPasswordError, RemoveFeedPasswordErrors, RemoveFeedPasswordResponse, RemoveFeedPasswordResponses, UpdateFeedData, UpdateFeedError, UpdateFeedErrors, UpdateFeedResponse, UpdateFeedResponses } from './types.gen.js';
|
|
2
|
+
export type { ChangeFeedPasswordData, ChangeFeedPasswordError, ChangeFeedPasswordErrors, ChangeFeedPasswordResponse, ChangeFeedPasswordResponses, ClientOptions, Created, DeleteFeedData, DeleteFeedError, DeleteFeedErrors, DeleteFeedResponse, DeleteFeedResponses, DeleteNoteData, DeleteNoteError, DeleteNoteErrors, DeleteNoteResponse, DeleteNoteResponses, EditNoteData, EditNoteError, EditNoteErrors, EditNoteResponse, EditNoteResponses, Error, Feed, FeedSettings, GetFeedData, GetFeedError, GetFeedErrors, GetFeedResponse, GetFeedResponses, GetNoteData, GetNoteError, GetNoteErrors, GetNoteResponse, GetNoteResponses, GetOpenApiData, GetOpenApiResponse, GetOpenApiResponses, GetReadFeedData, GetReadFeedError, GetReadFeedErrors, GetReadFeedResponse, GetReadFeedResponses, GetReadNoteData, GetReadNoteError, GetReadNoteErrors, GetReadNoteResponse, GetReadNoteResponses, ListNotesData, ListNotesError, ListNotesErrors, ListNotesResponse, ListNotesResponses, ListReadNotesData, ListReadNotesError, ListReadNotesErrors, ListReadNotesResponse, ListReadNotesResponses, MultipartNote, Note, NoteEdited, NoteList, NoteMeta, PasswordJson, PatchNoteData, PatchNoteError, PatchNoteErrors, PatchNoteResponse, PatchNoteResponses, Posted, PostNoteData, PostNoteError, PostNoteErrors, PostNoteResponse, PostNoteResponses, ReadFeed, RemoveFeedPasswordData, RemoveFeedPasswordError, RemoveFeedPasswordErrors, RemoveFeedPasswordResponse, RemoveFeedPasswordResponses, UpdateFeedData, UpdateFeedError, UpdateFeedErrors, UpdateFeedResponse, UpdateFeedResponses } from './types.gen.js';
|
|
@@ -22,7 +22,7 @@ export declare const listNotes: <ThrowOnError extends boolean = false>(options:
|
|
|
22
22
|
/**
|
|
23
23
|
* Post a note
|
|
24
24
|
*
|
|
25
|
-
* The body is the note, a file, and `Content-Type` says which kind: `text/markdown` (UTF-8, at most 102400 bytes), or an image, `image/png`, `image/jpeg`, `image/gif` or `image/webp` (at most NOTEFEED_MAX_IMAGE_BYTES, default 5 MiB). Nothing is guessed: any other type, or none, is `415`, and so is a body that is not what the type says (an image is recognized by its first bytes; SVG is refused). It is stored byte for byte, with no resizing and no metadata stripped (EXIF such as GPS position stays in an image). Creates the feed with its first note, optionally protected by its own password (`X-Feed-Password`; 1 to 256 printable ASCII characters, with no space at the start or end) and with the read id in `X-Read-Id`; both are only used by the post that creates the feed. Posting to a protected feed needs its password. Also served at `POST /{feed}`, the short form curl one-liners use. The response names the note's `file` and where it is served, `file_url`, under the feed's read id (public like the read link). Metadata goes in headers: `X-Note-Title`, `X-Note-Tags` (at most 10 tags, each 1 to 32 characters of letters, digits, `-`, `_`, `.` and `:`; case is folded to lowercase, duplicates are removed), `X-Note-Alt` (images), `X-Note-Name` (the original file name).
|
|
25
|
+
* The body is the note, a file, and `Content-Type` says which kind: `text/markdown` (UTF-8, at most 102400 bytes), or an image, `image/png`, `image/jpeg`, `image/gif` or `image/webp` (at most NOTEFEED_MAX_IMAGE_BYTES, default 5 MiB). Nothing is guessed: any other type, or none, is `415`, and so is a body that is not what the type says (an image is recognized by its first bytes; SVG is refused). It is stored byte for byte, with no resizing and no metadata stripped (EXIF such as GPS position stays in an image). Creates the feed with its first note, optionally protected by its own password (`X-Feed-Password`; 1 to 256 printable ASCII characters, with no space at the start or end) and with the read id in `X-Read-Id`; both are only used by the post that creates the feed. Posting to a protected feed needs its password. Also served at `POST /{feed}`, the short form curl one-liners use. The response names the note's `file` and where it is served, `file_url`, under the feed's read id (public like the read link). Metadata goes in headers: `X-Note-Title`, `X-Note-Tags` (at most 10 tags, each 1 to 32 characters of letters, digits, `-`, `_`, `.` and `:`; case is folded to lowercase, duplicates are removed), `X-Note-Alt` (images), `X-Note-Name` (the original file name). A markdown note with its pictures is one `multipart/form-data` request: a `text` part (the markdown, a field or a file part; a file part keeps its line breaks, a field's are sent as CRLF), `file` parts (up to 10 pictures, each with its file name and image `Content-Type`) and `alt.<file name>` fields. The pictures are stored first, each as its own note named by its file name, then the text with its references to them (``, `[x]: chart.png`, as written or percent-decoded) swapped for the stored files; a picture it never refers to is appended as ``. Everything is checked before the first write, and a failed write removes what the request stored: all or nothing. `X-Note-Alt` and `X-Note-Name` are 400. The answer has `attachments`, the stored pictures in the order of the `file` parts. The `text` part is optional: `X-Note-Title` goes on the text note and `X-Note-Tags` on every note; with no `text` part only the pictures are stored, each with the title, and the answer's top level is the first picture. A refused multipart post that would have created a protected feed creates nothing.
|
|
26
26
|
*/
|
|
27
27
|
export declare const postNote: <ThrowOnError extends boolean = false>(options: Options<PostNoteData, ThrowOnError>) => RequestResult<PostNoteResponses, PostNoteErrors, ThrowOnError>;
|
|
28
28
|
/**
|
|
@@ -44,7 +44,7 @@ export declare const patchNote: <ThrowOnError extends boolean = false>(options:
|
|
|
44
44
|
/**
|
|
45
45
|
* Replace a note's content
|
|
46
46
|
*
|
|
47
|
-
* The body is the new file, with the same rules as posting: a `Content-Type` that is one of the accepted types, a body that is what it declares. A note keeps its type, so the type must be the note's own (`415` otherwise). Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title or alt text with `PATCH`. Needs the feed's password if it has one, and counts against the post rate limit. Read links can't edit.
|
|
47
|
+
* The body is the new file, with the same rules as posting: a `Content-Type` that is one of the accepted types, a body that is what it declares. A note keeps its type, so the type must be the note's own (`415` otherwise). Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title or alt text with `PATCH`. Needs the feed's password if it has one, and counts against the post rate limit. Read links can't edit. A markdown note with its pictures is one `multipart/form-data` request: a `text` part (the markdown, a field or a file part; a file part keeps its line breaks, a field's are sent as CRLF), `file` parts (up to 10 pictures, each with its file name and image `Content-Type`) and `alt.<file name>` fields. The pictures are stored first, each as its own note named by its file name, then the text with its references to them (``, `[x]: chart.png`, as written or percent-decoded) swapped for the stored files; a picture it never refers to is appended as ``. Everything is checked before the first write, and a failed write removes what the request stored: all or nothing. `X-Note-Alt` and `X-Note-Name` are 400. The answer has `attachments`, the stored pictures in the order of the `file` parts. On a `PUT` the `text` part is required and the note must be a markdown note; the note keeps its own title and tags, `X-Note-Tags` goes on the new pictures. A raw body ignores `X-Note-Tags`. The note is looked up first: a missing note is `404` and an image note `415` whatever the body holds.
|
|
48
48
|
*/
|
|
49
49
|
export declare const editNote: <ThrowOnError extends boolean = false>(options: Options<EditNoteData, ThrowOnError>) => RequestResult<EditNoteResponses, EditNoteErrors, ThrowOnError>;
|
|
50
50
|
/**
|
|
@@ -62,7 +62,7 @@ export declare const getFeed: <ThrowOnError extends boolean = false>(options: Op
|
|
|
62
62
|
/**
|
|
63
63
|
* Change a feed's settings
|
|
64
64
|
*
|
|
65
|
-
* Replaces both the title (at most 100 characters) and the description (at most 500); surrounding whitespace is trimmed and control characters are refused. `show_sender` (default true) shows who posted each note to readers; omitted leaves it as it is. `read_id` gives the feed another read link (3 to 64 characters: a-z, 0-9, - and _; empty for a random one): the old id is freed and answers like an unknown read id until another feed takes it, and the notes are not edited (a relative image link follows the new id, a full URL does not). A short readable read id is guessable, so protect the feed with a password if that matters. An instance can turn chosen read ids off (NOTEFEED_ALLOW_CUSTOM_IDS=0): then only an empty `read_id` is accepted. `image` is the file name `uploadImage` returned for this feed (title image), empty to remove it, or omitted to leave it as it is; any other value is a 400. Needs the feed's password if it has one, and counts against the post rate limit. Only on a feed that exists: it is created by its first note. Read links can't change settings.
|
|
65
|
+
* Replaces both the title (at most 100 characters) and the description (at most 500); surrounding whitespace is trimmed and control and text-direction override characters are refused. `show_sender` (default true) shows who posted each note to readers; omitted leaves it as it is. `read_id` gives the feed another read link (3 to 64 characters: a-z, 0-9, - and _; empty for a random one): the old id is freed and answers like an unknown read id until another feed takes it, and the notes are not edited (a relative image link follows the new id, a full URL does not). A short readable read id is guessable, so protect the feed with a password if that matters. An instance can turn chosen read ids off (NOTEFEED_ALLOW_CUSTOM_IDS=0): then only an empty `read_id` is accepted. `image` is the file name `uploadImage` returned for this feed (title image), empty to remove it, or omitted to leave it as it is; any other value is a 400. Needs the feed's password if it has one, and counts against the post rate limit. Only on a feed that exists: it is created by its first note. Read links can't change settings.
|
|
66
66
|
*/
|
|
67
67
|
export declare const updateFeed: <ThrowOnError extends boolean = false>(options: Options<UpdateFeedData, ThrowOnError>) => RequestResult<UpdateFeedResponses, UpdateFeedErrors, ThrowOnError>;
|
|
68
68
|
/**
|
|
@@ -13,7 +13,7 @@ export const listNotes = (options) => (options.client ?? client).get({
|
|
|
13
13
|
/**
|
|
14
14
|
* Post a note
|
|
15
15
|
*
|
|
16
|
-
* The body is the note, a file, and `Content-Type` says which kind: `text/markdown` (UTF-8, at most 102400 bytes), or an image, `image/png`, `image/jpeg`, `image/gif` or `image/webp` (at most NOTEFEED_MAX_IMAGE_BYTES, default 5 MiB). Nothing is guessed: any other type, or none, is `415`, and so is a body that is not what the type says (an image is recognized by its first bytes; SVG is refused). It is stored byte for byte, with no resizing and no metadata stripped (EXIF such as GPS position stays in an image). Creates the feed with its first note, optionally protected by its own password (`X-Feed-Password`; 1 to 256 printable ASCII characters, with no space at the start or end) and with the read id in `X-Read-Id`; both are only used by the post that creates the feed. Posting to a protected feed needs its password. Also served at `POST /{feed}`, the short form curl one-liners use. The response names the note's `file` and where it is served, `file_url`, under the feed's read id (public like the read link). Metadata goes in headers: `X-Note-Title`, `X-Note-Tags` (at most 10 tags, each 1 to 32 characters of letters, digits, `-`, `_`, `.` and `:`; case is folded to lowercase, duplicates are removed), `X-Note-Alt` (images), `X-Note-Name` (the original file name).
|
|
16
|
+
* The body is the note, a file, and `Content-Type` says which kind: `text/markdown` (UTF-8, at most 102400 bytes), or an image, `image/png`, `image/jpeg`, `image/gif` or `image/webp` (at most NOTEFEED_MAX_IMAGE_BYTES, default 5 MiB). Nothing is guessed: any other type, or none, is `415`, and so is a body that is not what the type says (an image is recognized by its first bytes; SVG is refused). It is stored byte for byte, with no resizing and no metadata stripped (EXIF such as GPS position stays in an image). Creates the feed with its first note, optionally protected by its own password (`X-Feed-Password`; 1 to 256 printable ASCII characters, with no space at the start or end) and with the read id in `X-Read-Id`; both are only used by the post that creates the feed. Posting to a protected feed needs its password. Also served at `POST /{feed}`, the short form curl one-liners use. The response names the note's `file` and where it is served, `file_url`, under the feed's read id (public like the read link). Metadata goes in headers: `X-Note-Title`, `X-Note-Tags` (at most 10 tags, each 1 to 32 characters of letters, digits, `-`, `_`, `.` and `:`; case is folded to lowercase, duplicates are removed), `X-Note-Alt` (images), `X-Note-Name` (the original file name). A markdown note with its pictures is one `multipart/form-data` request: a `text` part (the markdown, a field or a file part; a file part keeps its line breaks, a field's are sent as CRLF), `file` parts (up to 10 pictures, each with its file name and image `Content-Type`) and `alt.<file name>` fields. The pictures are stored first, each as its own note named by its file name, then the text with its references to them (``, `[x]: chart.png`, as written or percent-decoded) swapped for the stored files; a picture it never refers to is appended as ``. Everything is checked before the first write, and a failed write removes what the request stored: all or nothing. `X-Note-Alt` and `X-Note-Name` are 400. The answer has `attachments`, the stored pictures in the order of the `file` parts. The `text` part is optional: `X-Note-Title` goes on the text note and `X-Note-Tags` on every note; with no `text` part only the pictures are stored, each with the title, and the answer's top level is the first picture. A refused multipart post that would have created a protected feed creates nothing.
|
|
17
17
|
*/
|
|
18
18
|
export const postNote = (options) => (options.client ?? client).post({
|
|
19
19
|
bodySerializer: null,
|
|
@@ -60,7 +60,7 @@ export const patchNote = (options) => (options.client ?? client).patch({
|
|
|
60
60
|
/**
|
|
61
61
|
* Replace a note's content
|
|
62
62
|
*
|
|
63
|
-
* The body is the new file, with the same rules as posting: a `Content-Type` that is one of the accepted types, a body that is what it declares. A note keeps its type, so the type must be the note's own (`415` otherwise). Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title or alt text with `PATCH`. Needs the feed's password if it has one, and counts against the post rate limit. Read links can't edit.
|
|
63
|
+
* The body is the new file, with the same rules as posting: a `Content-Type` that is one of the accepted types, a body that is what it declares. A note keeps its type, so the type must be the note's own (`415` otherwise). Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title or alt text with `PATCH`. Needs the feed's password if it has one, and counts against the post rate limit. Read links can't edit. A markdown note with its pictures is one `multipart/form-data` request: a `text` part (the markdown, a field or a file part; a file part keeps its line breaks, a field's are sent as CRLF), `file` parts (up to 10 pictures, each with its file name and image `Content-Type`) and `alt.<file name>` fields. The pictures are stored first, each as its own note named by its file name, then the text with its references to them (``, `[x]: chart.png`, as written or percent-decoded) swapped for the stored files; a picture it never refers to is appended as ``. Everything is checked before the first write, and a failed write removes what the request stored: all or nothing. `X-Note-Alt` and `X-Note-Name` are 400. The answer has `attachments`, the stored pictures in the order of the `file` parts. On a `PUT` the `text` part is required and the note must be a markdown note; the note keeps its own title and tags, `X-Note-Tags` goes on the new pictures. A raw body ignores `X-Note-Tags`. The note is looked up first: a missing note is `404` and an image note `415` whatever the body holds.
|
|
64
64
|
*/
|
|
65
65
|
export const editNote = (options) => (options.client ?? client).put({
|
|
66
66
|
bodySerializer: null,
|
|
@@ -95,7 +95,7 @@ export const getFeed = (options) => (options.client ?? client).get({
|
|
|
95
95
|
/**
|
|
96
96
|
* Change a feed's settings
|
|
97
97
|
*
|
|
98
|
-
* Replaces both the title (at most 100 characters) and the description (at most 500); surrounding whitespace is trimmed and control characters are refused. `show_sender` (default true) shows who posted each note to readers; omitted leaves it as it is. `read_id` gives the feed another read link (3 to 64 characters: a-z, 0-9, - and _; empty for a random one): the old id is freed and answers like an unknown read id until another feed takes it, and the notes are not edited (a relative image link follows the new id, a full URL does not). A short readable read id is guessable, so protect the feed with a password if that matters. An instance can turn chosen read ids off (NOTEFEED_ALLOW_CUSTOM_IDS=0): then only an empty `read_id` is accepted. `image` is the file name `uploadImage` returned for this feed (title image), empty to remove it, or omitted to leave it as it is; any other value is a 400. Needs the feed's password if it has one, and counts against the post rate limit. Only on a feed that exists: it is created by its first note. Read links can't change settings.
|
|
98
|
+
* Replaces both the title (at most 100 characters) and the description (at most 500); surrounding whitespace is trimmed and control and text-direction override characters are refused. `show_sender` (default true) shows who posted each note to readers; omitted leaves it as it is. `read_id` gives the feed another read link (3 to 64 characters: a-z, 0-9, - and _; empty for a random one): the old id is freed and answers like an unknown read id until another feed takes it, and the notes are not edited (a relative image link follows the new id, a full URL does not). A short readable read id is guessable, so protect the feed with a password if that matters. An instance can turn chosen read ids off (NOTEFEED_ALLOW_CUSTOM_IDS=0): then only an empty `read_id` is accepted. `image` is the file name `uploadImage` returned for this feed (title image), empty to remove it, or omitted to leave it as it is; any other value is a 400. Needs the feed's password if it has one, and counts against the post rate limit. Only on a feed that exists: it is created by its first note. Read links can't change settings.
|
|
99
99
|
*/
|
|
100
100
|
export const updateFeed = (options) => (options.client ?? client).put({
|
|
101
101
|
security: [{ scheme: 'bearer', type: 'http' }],
|
|
@@ -88,6 +88,104 @@ export type Created = {
|
|
|
88
88
|
*/
|
|
89
89
|
file_url: string | null;
|
|
90
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* The note the post is about: its text note, or with no `text` part its first picture
|
|
93
|
+
*/
|
|
94
|
+
export type Posted = {
|
|
95
|
+
id: string;
|
|
96
|
+
/**
|
|
97
|
+
* The note's page in the web UI
|
|
98
|
+
*/
|
|
99
|
+
url: string;
|
|
100
|
+
/**
|
|
101
|
+
* The feed's page in the web UI
|
|
102
|
+
*/
|
|
103
|
+
feed_url: string;
|
|
104
|
+
/**
|
|
105
|
+
* The feed's read-only RSS link, safe to share; null only if the server can't read the feed's stored read id, or if that id and the derived one both belong to other feeds
|
|
106
|
+
*/
|
|
107
|
+
read_url: string | null;
|
|
108
|
+
/**
|
|
109
|
+
* The note's file name, `<id>.<extension>`. For an image note, pass it as a feed's `image` setting
|
|
110
|
+
*/
|
|
111
|
+
file: string;
|
|
112
|
+
/**
|
|
113
|
+
* Where the note's file is served, absolute, under the feed's read id (public like the read link); null while the feed has no read link
|
|
114
|
+
*/
|
|
115
|
+
file_url: string | null;
|
|
116
|
+
/**
|
|
117
|
+
* A multipart request's pictures, one per `file` part, in their order; absent for a raw body
|
|
118
|
+
*/
|
|
119
|
+
attachments?: Array<Created>;
|
|
120
|
+
};
|
|
121
|
+
export type NoteEdited = {
|
|
122
|
+
/**
|
|
123
|
+
* The note's id: a UTC time to the second plus a random UUID for notes made here; any name without a dot for a file placed by hand
|
|
124
|
+
*/
|
|
125
|
+
id: string;
|
|
126
|
+
/**
|
|
127
|
+
* The media type of the note's file: `text/markdown`, `image/png`, `image/jpeg`, `image/gif` or `image/webp`
|
|
128
|
+
*/
|
|
129
|
+
type: string;
|
|
130
|
+
/**
|
|
131
|
+
* The note's file name, `<id>.<extension>`
|
|
132
|
+
*/
|
|
133
|
+
file: string;
|
|
134
|
+
/**
|
|
135
|
+
* Where the note's file is served, absolute, under the feed's read id (public like the read link); null while the feed has no read link
|
|
136
|
+
*/
|
|
137
|
+
file_url: string | null;
|
|
138
|
+
/**
|
|
139
|
+
* The size of the note's file in bytes
|
|
140
|
+
*/
|
|
141
|
+
size: number;
|
|
142
|
+
/**
|
|
143
|
+
* The title set for the note, else the first heading or the first non-empty line of a markdown note, else the picture's alt text; may be empty
|
|
144
|
+
*/
|
|
145
|
+
title: string;
|
|
146
|
+
/**
|
|
147
|
+
* The note's text, byte-for-byte as posted: for a text type (markdown) only; absent for a picture
|
|
148
|
+
*/
|
|
149
|
+
content?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Alternative text of an image note, when it has one
|
|
152
|
+
*/
|
|
153
|
+
alt?: string;
|
|
154
|
+
/**
|
|
155
|
+
* The file name an image was posted with, when it came with one
|
|
156
|
+
*/
|
|
157
|
+
name?: string;
|
|
158
|
+
/**
|
|
159
|
+
* When the note was posted (UTC)
|
|
160
|
+
*/
|
|
161
|
+
created_at: string;
|
|
162
|
+
/**
|
|
163
|
+
* The note's page in the web UI
|
|
164
|
+
*/
|
|
165
|
+
url: string;
|
|
166
|
+
/**
|
|
167
|
+
* Verified sign-in name of the poster; absent when the note was posted without a sign-in
|
|
168
|
+
*/
|
|
169
|
+
sender?: string | null;
|
|
170
|
+
/**
|
|
171
|
+
* Labels the poster gave the note (not verified, and shown to readers like the note itself); empty when none
|
|
172
|
+
*/
|
|
173
|
+
tags: Array<string>;
|
|
174
|
+
/**
|
|
175
|
+
* A multipart request's pictures, one per `file` part, in their order; absent for a raw body
|
|
176
|
+
*/
|
|
177
|
+
attachments?: Array<Created>;
|
|
178
|
+
};
|
|
179
|
+
export type MultipartNote = {
|
|
180
|
+
/**
|
|
181
|
+
* The markdown note (UTF-8): a field, or a file part (its name is ignored; its type, if any, `text/markdown` or `application/octet-stream`) to keep its line breaks as they are, since a form field's are sent as CRLF. At most one; required on a PUT. Its references to the files (``, `[x]: chart.png`) are swapped for the stored files; a file it never refers to is appended as ``
|
|
182
|
+
*/
|
|
183
|
+
text?: string;
|
|
184
|
+
/**
|
|
185
|
+
* A picture: up to 10 parts, each with a file name (one path segment, 1 to 200 characters, unique in the request) and its image `Content-Type`. An `alt.<file name>` field gives one its alternative text
|
|
186
|
+
*/
|
|
187
|
+
file?: Array<Blob | File>;
|
|
188
|
+
};
|
|
91
189
|
export type Error = {
|
|
92
190
|
/**
|
|
93
191
|
* A short reason, for people
|
|
@@ -100,11 +198,11 @@ export type Error = {
|
|
|
100
198
|
};
|
|
101
199
|
export type NoteMeta = {
|
|
102
200
|
/**
|
|
103
|
-
* The note's title, at most 100 characters, one line; empty or left out means the title is taken from the text (a markdown note) or there is none (an image)
|
|
201
|
+
* The note's title, at most 100 characters, one line (control and text-direction override characters are refused); empty or left out means the title is taken from the text (a markdown note) or there is none (an image)
|
|
104
202
|
*/
|
|
105
203
|
title?: string;
|
|
106
204
|
/**
|
|
107
|
-
* Alternative text of an image note, at most 500 characters, one line
|
|
205
|
+
* Alternative text of an image note, at most 500 characters, one line (control and text-direction override characters are refused)
|
|
108
206
|
*/
|
|
109
207
|
alt?: string;
|
|
110
208
|
};
|
|
@@ -116,11 +214,11 @@ export type PasswordJson = {
|
|
|
116
214
|
};
|
|
117
215
|
export type FeedSettings = {
|
|
118
216
|
/**
|
|
119
|
-
* Display title, at most 100 characters, one line; empty means none (the feed's name is shown)
|
|
217
|
+
* Display title, at most 100 characters, one line (control and text-direction override characters are refused); empty means none (the feed's name is shown)
|
|
120
218
|
*/
|
|
121
219
|
title: string;
|
|
122
220
|
/**
|
|
123
|
-
* Description, at most 500 characters, one line; may be empty
|
|
221
|
+
* Description, at most 500 characters, one line (control and text-direction override characters are refused); may be empty
|
|
124
222
|
*/
|
|
125
223
|
description: string;
|
|
126
224
|
/**
|
|
@@ -142,11 +240,11 @@ export type Feed = {
|
|
|
142
240
|
*/
|
|
143
241
|
name: string;
|
|
144
242
|
/**
|
|
145
|
-
* Display title, at most 100 characters, one line; empty means none (the feed's name is shown)
|
|
243
|
+
* Display title, at most 100 characters, one line (control and text-direction override characters are refused); empty means none (the feed's name is shown)
|
|
146
244
|
*/
|
|
147
245
|
title: string;
|
|
148
246
|
/**
|
|
149
|
-
* Description, at most 500 characters, one line; may be empty
|
|
247
|
+
* Description, at most 500 characters, one line (control and text-direction override characters are refused); may be empty
|
|
150
248
|
*/
|
|
151
249
|
description: string;
|
|
152
250
|
/**
|
|
@@ -168,11 +266,11 @@ export type Feed = {
|
|
|
168
266
|
};
|
|
169
267
|
export type ReadFeed = {
|
|
170
268
|
/**
|
|
171
|
-
* Display title, at most 100 characters, one line; empty means none (the feed's name is shown)
|
|
269
|
+
* Display title, at most 100 characters, one line (control and text-direction override characters are refused); empty means none (the feed's name is shown)
|
|
172
270
|
*/
|
|
173
271
|
title: string;
|
|
174
272
|
/**
|
|
175
|
-
* Description, at most 500 characters, one line; may be empty
|
|
273
|
+
* Description, at most 500 characters, one line (control and text-direction override characters are refused); may be empty
|
|
176
274
|
*/
|
|
177
275
|
description: string;
|
|
178
276
|
/**
|
|
@@ -247,7 +345,7 @@ export type PostNoteData = {
|
|
|
247
345
|
*/
|
|
248
346
|
'X-Read-Id'?: string;
|
|
249
347
|
/**
|
|
250
|
-
* The note's title, for a raw body; a JSON or form body's own `title` wins. At most 100 characters, one line.
|
|
348
|
+
* The note's title, for a raw body; a JSON or form body's own `title` wins. At most 100 characters, one line, with no control or text-direction override characters.
|
|
251
349
|
*/
|
|
252
350
|
'X-Note-Title'?: string;
|
|
253
351
|
/**
|
|
@@ -274,7 +372,7 @@ export type PostNoteData = {
|
|
|
274
372
|
};
|
|
275
373
|
export type PostNoteErrors = {
|
|
276
374
|
/**
|
|
277
|
-
* Invalid or reserved feed name; a blank note; a bad title, alt text or tags; a new password that is not printable ASCII
|
|
375
|
+
* Invalid or reserved feed name; a blank note; a bad title, alt text or tags; a new password that is not printable ASCII; a multipart body with an unexpected part, no `text` and no `file`, more than 10 files, a bad or repeated file name, a text sent with pictures that takes too long to read (`NOTEFEED_PARSE_TIMEOUT_MS`), or `X-Note-Alt` / `X-Note-Name`
|
|
278
376
|
*/
|
|
279
377
|
400: Error;
|
|
280
378
|
/**
|
|
@@ -286,11 +384,11 @@ export type PostNoteErrors = {
|
|
|
286
384
|
*/
|
|
287
385
|
409: Error;
|
|
288
386
|
/**
|
|
289
|
-
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES
|
|
387
|
+
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES (each picture of a multipart body too), or a multipart body over 102400 bytes plus 10 images plus 64 KiB
|
|
290
388
|
*/
|
|
291
389
|
413: Error;
|
|
292
390
|
/**
|
|
293
|
-
* Content-Type missing or not one of the accepted types, or the body is not what it declares
|
|
391
|
+
* Content-Type missing or not one of the accepted types, or the body (or a multipart body's picture) is not what it declares
|
|
294
392
|
*/
|
|
295
393
|
415: Error;
|
|
296
394
|
/**
|
|
@@ -305,9 +403,9 @@ export type PostNoteErrors = {
|
|
|
305
403
|
export type PostNoteError = PostNoteErrors[keyof PostNoteErrors];
|
|
306
404
|
export type PostNoteResponses = {
|
|
307
405
|
/**
|
|
308
|
-
* Stored
|
|
406
|
+
* Stored: the note, and with a multipart body its pictures
|
|
309
407
|
*/
|
|
310
|
-
201:
|
|
408
|
+
201: Posted;
|
|
311
409
|
};
|
|
312
410
|
export type PostNoteResponse = PostNoteResponses[keyof PostNoteResponses];
|
|
313
411
|
export type DeleteNoteData = {
|
|
@@ -465,6 +563,10 @@ export type EditNoteData = {
|
|
|
465
563
|
* The feed's own password, when it has one: to post, list or get, and (as the current password) to change or remove it. On the `POST` that creates a feed it sets the feed's password; on a `POST` to an existing feed that has none it answers 409. An empty value is the same as no header, so a `POST` with an empty one creates an open feed.
|
|
466
564
|
*/
|
|
467
565
|
'X-Feed-Password'?: string;
|
|
566
|
+
/**
|
|
567
|
+
* Only for a multipart body: the tags go on the new pictures (the note keeps its own). A raw body ignores it. Comma-separated, empty is none.
|
|
568
|
+
*/
|
|
569
|
+
'X-Note-Tags'?: string;
|
|
468
570
|
};
|
|
469
571
|
path: {
|
|
470
572
|
/**
|
|
@@ -481,7 +583,7 @@ export type EditNoteData = {
|
|
|
481
583
|
};
|
|
482
584
|
export type EditNoteErrors = {
|
|
483
585
|
/**
|
|
484
|
-
* Invalid or reserved feed name; a blank note
|
|
586
|
+
* Invalid or reserved feed name; a blank note; a multipart body with an unexpected part, no `text`, more than 10 files, a bad or repeated file name, a text sent with pictures that takes too long to read (`NOTEFEED_PARSE_TIMEOUT_MS`), or `X-Note-Alt` / `X-Note-Name`
|
|
485
587
|
*/
|
|
486
588
|
400: Error;
|
|
487
589
|
/**
|
|
@@ -493,24 +595,28 @@ export type EditNoteErrors = {
|
|
|
493
595
|
*/
|
|
494
596
|
404: Error;
|
|
495
597
|
/**
|
|
496
|
-
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES
|
|
598
|
+
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES (each picture of a multipart body too), or a multipart body over 102400 bytes plus 10 images plus 64 KiB
|
|
497
599
|
*/
|
|
498
600
|
413: Error;
|
|
499
601
|
/**
|
|
500
|
-
* Content-Type missing, not accepted or not the note's own type, or the body is not what it declares
|
|
602
|
+
* Content-Type missing, not accepted or not the note's own type (a multipart body is for a markdown note), or the body (or a picture) is not what it declares
|
|
501
603
|
*/
|
|
502
604
|
415: Error;
|
|
503
605
|
/**
|
|
504
606
|
* Too many posts, edits and deletes, or wrong passwords, from this client
|
|
505
607
|
*/
|
|
506
608
|
429: Error;
|
|
609
|
+
/**
|
|
610
|
+
* NOTEFEED_MAX_IMAGES_PER_FEED reached
|
|
611
|
+
*/
|
|
612
|
+
507: Error;
|
|
507
613
|
};
|
|
508
614
|
export type EditNoteError = EditNoteErrors[keyof EditNoteErrors];
|
|
509
615
|
export type EditNoteResponses = {
|
|
510
616
|
/**
|
|
511
|
-
* The note as it is now
|
|
617
|
+
* The note as it is now, and with a multipart body the new pictures
|
|
512
618
|
*/
|
|
513
|
-
200:
|
|
619
|
+
200: NoteEdited;
|
|
514
620
|
};
|
|
515
621
|
export type EditNoteResponse = EditNoteResponses[keyof EditNoteResponses];
|
|
516
622
|
export type DeleteFeedData = {
|
|
@@ -618,7 +724,7 @@ export type UpdateFeedData = {
|
|
|
618
724
|
};
|
|
619
725
|
export type UpdateFeedErrors = {
|
|
620
726
|
/**
|
|
621
|
-
* Invalid or reserved feed name, bad JSON, a title or description that is too long or has control characters, a malformed read id, a reserved feed's read id, or chosen read ids turned off
|
|
727
|
+
* Invalid or reserved feed name, bad JSON, a title or description that is too long or has control or text-direction override characters, a malformed read id, a reserved feed's read id, or chosen read ids turned off
|
|
622
728
|
*/
|
|
623
729
|
400: Error;
|
|
624
730
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notefeed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Client and CLI for notefeed, a self-hosted inbox for markdown notes that you read back as RSS.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Marcel Bruckner",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|
|
39
|
-
"url": "git+https://github.com/
|
|
39
|
+
"url": "git+https://github.com/notefeed/notefeed.git",
|
|
40
40
|
"directory": "packages/js"
|
|
41
41
|
},
|
|
42
|
-
"homepage": "https://docs.notefeed.me/clients/",
|
|
42
|
+
"homepage": "https://docs.notefeed.me/integrations/clients/",
|
|
43
43
|
"bugs": {
|
|
44
|
-
"url": "https://github.com/
|
|
44
|
+
"url": "https://github.com/notefeed/notefeed/issues"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^20",
|