notefeed 0.32.0 → 0.33.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 +2 -0
- package/dist/cli.js +12 -6
- package/dist/client.d.ts +3 -1
- package/dist/client.js +3 -1
- package/dist/generated/sdk.gen.d.ts +1 -1
- package/dist/generated/sdk.gen.js +1 -1
- package/dist/generated/types.gen.d.ts +31 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ for await (const note of client.notes()) console.log(note.date, note.title); //
|
|
|
25
25
|
|
|
26
26
|
Every note has a date, now unless you give one: `client.post(text, { date: "2025-03-01T09:30:00Z" })` (a `Date`, an ISO 8601 date-time with its offset, or a date alone for midnight UTC; any time from 1970 to 9999), or `notefeed post "…" --date 2025-03-01`. The note takes its place in the feed by that date. A date in the future schedules the note: readers see it from then on. `await client.update(id, { date })` (`notefeed update <id> --date …`) moves a note.
|
|
27
27
|
|
|
28
|
+
A note posted with `draft: true` (`notefeed post "…" --draft`) is a draft: readers don't see it, or its pictures, until `client.update(id, { draft: false })` (`notefeed update <id> --publish`) publishes it at its date; `draft: true` (`--draft`) hides it again.
|
|
29
|
+
|
|
28
30
|
`Client.fromEnv()` reads `NOTEFEED_URL` / `NOTEFEED_FEED` / `NOTEFEED_PASSWORD`; so does the `notefeed` command, unless given `--url` / `--feed` / `--password`.
|
|
29
31
|
|
|
30
32
|
A feed can have its own password, which gates reading, listing and posting to it. Pass `feedPassword: "..."` to `new Client(...)` (or per call, e.g. `client.post(text, { feedPassword })`), or set `NOTEFEED_FEED_PASSWORD`, which `fromEnv()` and the `notefeed` command both read (there is deliberately no flag, so it stays out of shell history). It is sent as `X-Feed-Password`; `Authorization` stays the instance password. A feed password is 1 to 256 printable ASCII characters with no space at the start or end; an empty one is the same as none.
|
package/dist/cli.js
CHANGED
|
@@ -7,9 +7,9 @@ import { Client, ConfigError, NotefeedError } from "./client.js";
|
|
|
7
7
|
class UsageError extends Error {
|
|
8
8
|
}
|
|
9
9
|
const USAGE = [
|
|
10
|
-
"usage: notefeed post <text | - | --file PATH> [--type MEDIA_TYPE] [--title TITLE] [--tag TAG]... [--attach PATH]... [--date WHEN] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
10
|
+
"usage: notefeed post <text | - | --file PATH> [--type MEDIA_TYPE] [--title TITLE] [--tag TAG]... [--attach PATH]... [--date WHEN] [--draft] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
11
11
|
" notefeed edit <id> <text | - | --file PATH> [--type MEDIA_TYPE] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
12
|
-
" notefeed update <id> [--title TITLE] [--alt ALT] [--tags LIST] [--date WHEN] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
12
|
+
" notefeed update <id> [--title TITLE] [--alt ALT] [--tags LIST] [--date WHEN] [--draft | --publish] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
13
13
|
" notefeed delete <id> [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
14
14
|
" notefeed notes [--limit N] [--tag TAG] [--json] [--url URL] [--feed FEED] [--password PASSWORD]",
|
|
15
15
|
].join("\n");
|
|
@@ -32,6 +32,8 @@ export async function main(argv, io = process) {
|
|
|
32
32
|
tag: { type: "string", multiple: true },
|
|
33
33
|
tags: { type: "string" },
|
|
34
34
|
date: { type: "string" },
|
|
35
|
+
draft: { type: "boolean" },
|
|
36
|
+
publish: { type: "boolean" },
|
|
35
37
|
attach: { type: "string", multiple: true },
|
|
36
38
|
limit: { type: "string" },
|
|
37
39
|
json: { type: "boolean" },
|
|
@@ -55,7 +57,7 @@ export async function main(argv, io = process) {
|
|
|
55
57
|
const noText = attachments.length > 0 && text === undefined && !values.file;
|
|
56
58
|
const input = noText ? { content: null, type: undefined, name: undefined } : await read(text, values.file, values.type, io);
|
|
57
59
|
// The server refuses a file name next to attachments: the text has none then.
|
|
58
|
-
const note = await client(values).post(input.content, { type: input.type, title: values.title, tags: values.tag, date: values.date, name: attachments.length ? undefined : input.name, attachments });
|
|
60
|
+
const note = await client(values).post(input.content, { type: input.type, title: values.title, tags: values.tag, date: values.date, draft: values.draft, name: attachments.length ? undefined : input.name, attachments });
|
|
59
61
|
io.stdout.write(`${[...(noText ? [] : [note.url]), ...note.attachments.map((a) => a.url)].join("\n")}\n`);
|
|
60
62
|
return 0;
|
|
61
63
|
}
|
|
@@ -66,11 +68,15 @@ export async function main(argv, io = process) {
|
|
|
66
68
|
return 0;
|
|
67
69
|
}
|
|
68
70
|
if (command === "update" && text !== undefined && !rest.length) {
|
|
69
|
-
if (values.
|
|
70
|
-
throw new UsageError("give --
|
|
71
|
+
if (values.draft && values.publish)
|
|
72
|
+
throw new UsageError("give --draft or --publish, not both");
|
|
73
|
+
// --draft makes the note a draft (#265), --publish publishes it; either alone is an update.
|
|
74
|
+
const draft = values.draft ? true : values.publish ? false : undefined;
|
|
75
|
+
if (values.title === undefined && values.alt === undefined && values.tags === undefined && values.date === undefined && draft === undefined)
|
|
76
|
+
throw new UsageError("give --title, --alt, --tags, --date and/or --draft or --publish");
|
|
71
77
|
// --tags is the whole new list, comma-separated; "" removes them all.
|
|
72
78
|
const tags = values.tags?.split(",").map((t) => t.trim()).filter(Boolean);
|
|
73
|
-
const note = await client(values).update(text, { title: values.title, alt: values.alt, tags, date: values.date });
|
|
79
|
+
const note = await client(values).update(text, { title: values.title, alt: values.alt, tags, date: values.date, draft });
|
|
74
80
|
io.stdout.write(`${note.url}\n`);
|
|
75
81
|
return 0;
|
|
76
82
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -89,6 +89,7 @@ export declare class Client {
|
|
|
89
89
|
alt?: string;
|
|
90
90
|
name?: string;
|
|
91
91
|
date?: string | Date;
|
|
92
|
+
draft?: boolean;
|
|
92
93
|
readId?: string;
|
|
93
94
|
licenseKey?: string;
|
|
94
95
|
attachments?: Attachment[];
|
|
@@ -102,12 +103,13 @@ export declare class Client {
|
|
|
102
103
|
feedPassword?: string;
|
|
103
104
|
type?: string;
|
|
104
105
|
}): Promise<Note>;
|
|
105
|
-
/** Set a note's title, alt text (for pictures), tags
|
|
106
|
+
/** Set a note's title, alt text (for pictures), tags, date (as in post(); a future one schedules the note) and/or whether it is a draft (`false` publishes it, `true` hides it from readers again; its date stays); `""` removes a title or alt, so a markdown note's title follows its text again; `tags` replaces the whole list (`[]` removes them). Same options as post(). */
|
|
106
107
|
update(id: string, meta: {
|
|
107
108
|
title?: string;
|
|
108
109
|
alt?: string;
|
|
109
110
|
tags?: string[];
|
|
110
111
|
date?: string | Date;
|
|
112
|
+
draft?: boolean;
|
|
111
113
|
}, options?: {
|
|
112
114
|
feed?: string;
|
|
113
115
|
feedPassword?: string;
|
package/dist/client.js
CHANGED
|
@@ -160,6 +160,7 @@ export class Client {
|
|
|
160
160
|
...(own.title && { "X-Note-Title": headerValue(own.title) }),
|
|
161
161
|
...(own.tags?.length && { "X-Note-Tags": own.tags.join(",") }),
|
|
162
162
|
...(own.date && { "X-Note-Date": dateString(own.date) }),
|
|
163
|
+
...(own.draft && { "X-Note-Draft": "true" }),
|
|
163
164
|
...(own.readId && { "X-Read-Id": own.readId }),
|
|
164
165
|
...(own.licenseKey && { "X-License-Key": own.licenseKey }),
|
|
165
166
|
};
|
|
@@ -177,6 +178,7 @@ export class Client {
|
|
|
177
178
|
...(options.alt && { "X-Note-Alt": headerValue(options.alt) }),
|
|
178
179
|
...(options.name && { "X-Note-Name": headerValue(options.name) }),
|
|
179
180
|
...(options.date && { "X-Note-Date": dateString(options.date) }),
|
|
181
|
+
...(options.draft && { "X-Note-Draft": "true" }),
|
|
180
182
|
...(options.readId && { "X-Read-Id": options.readId }),
|
|
181
183
|
...(options.licenseKey && { "X-License-Key": options.licenseKey }),
|
|
182
184
|
};
|
|
@@ -189,7 +191,7 @@ export class Client {
|
|
|
189
191
|
const headers = { ...this.opts(options.feedPassword).headers, "Content-Type": type };
|
|
190
192
|
return this.call(editNote({ client: this.api, path: { feed, id }, body, headers, signal: AbortSignal.timeout(this.timeoutMs) }));
|
|
191
193
|
}
|
|
192
|
-
/** Set a note's title, alt text (for pictures), tags
|
|
194
|
+
/** Set a note's title, alt text (for pictures), tags, date (as in post(); a future one schedules the note) and/or whether it is a draft (`false` publishes it, `true` hides it from readers again; its date stays); `""` removes a title or alt, so a markdown note's title follows its text again; `tags` replaces the whole list (`[]` removes them). Same options as post(). */
|
|
193
195
|
async update(id, meta, options = {}) {
|
|
194
196
|
const feed = this.feedFor(options.feed);
|
|
195
197
|
const { date, ...rest } = meta;
|
|
@@ -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 as sent, default 10 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). Markdown is stored byte for byte. An image is stored processed, not as sent: turned the way its EXIF orientation says, scaled to at most 2560 px on its long side, encoded again in its own format (JPEG and WebP at quality 85, PNG lossless, an animated GIF or WebP keeps its frames), and without metadata (EXIF, GPS position, XMP, comments). Send it full size; one of more than 100 megapixels is `413`, and a body that does not decode as the image it declares is `415`. 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. Where licenses are sold, the post that creates the feed can bring a license key in `X-License-Key`, with or without a password; a feed password needs one, or the post is refused with `402`. 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), `X-Note-Date` (where it is placed in the feed: a past date backdates it, a future one schedules it). 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 ``. Several pictures may have the same file name (a phone calls every photo `image.jpg`): each is stored, and they are appended, but a text that refers to such a name is 400. 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, `X-Note-Tags` on every note, `X-Note-Date` on the text note (its pictures take the milliseconds just before it); 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.
|
|
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 as sent, default 10 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). Markdown is stored byte for byte. An image is stored processed, not as sent: turned the way its EXIF orientation says, scaled to at most 2560 px on its long side, encoded again in its own format (JPEG and WebP at quality 85, PNG lossless, an animated GIF or WebP keeps its frames), and without metadata (EXIF, GPS position, XMP, comments). Send it full size; one of more than 100 megapixels is `413`, and a body that does not decode as the image it declares is `415`. 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. Where licenses are sold, the post that creates the feed can bring a license key in `X-License-Key`, with or without a password; a feed password needs one, or the post is refused with `402`. 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), `X-Note-Date` (where it is placed in the feed: a past date backdates it, a future one schedules it), `X-Note-Draft` (`true`: a draft, which readers do not see until it is published). 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 ``. Several pictures may have the same file name (a phone calls every photo `image.jpg`): each is stored, and they are appended, but a text that refers to such a name is 400. 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, `X-Note-Tags` on every note, `X-Note-Date` on the text note (its pictures take the milliseconds just before it); 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
|
/**
|
|
@@ -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 as sent, default 10 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). Markdown is stored byte for byte. An image is stored processed, not as sent: turned the way its EXIF orientation says, scaled to at most 2560 px on its long side, encoded again in its own format (JPEG and WebP at quality 85, PNG lossless, an animated GIF or WebP keeps its frames), and without metadata (EXIF, GPS position, XMP, comments). Send it full size; one of more than 100 megapixels is `413`, and a body that does not decode as the image it declares is `415`. 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. Where licenses are sold, the post that creates the feed can bring a license key in `X-License-Key`, with or without a password; a feed password needs one, or the post is refused with `402`. 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), `X-Note-Date` (where it is placed in the feed: a past date backdates it, a future one schedules it). 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 ``. Several pictures may have the same file name (a phone calls every photo `image.jpg`): each is stored, and they are appended, but a text that refers to such a name is 400. 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, `X-Note-Tags` on every note, `X-Note-Date` on the text note (its pictures take the milliseconds just before it); 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.
|
|
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 as sent, default 10 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). Markdown is stored byte for byte. An image is stored processed, not as sent: turned the way its EXIF orientation says, scaled to at most 2560 px on its long side, encoded again in its own format (JPEG and WebP at quality 85, PNG lossless, an animated GIF or WebP keeps its frames), and without metadata (EXIF, GPS position, XMP, comments). Send it full size; one of more than 100 megapixels is `413`, and a body that does not decode as the image it declares is `415`. 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. Where licenses are sold, the post that creates the feed can bring a license key in `X-License-Key`, with or without a password; a feed password needs one, or the post is refused with `402`. 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), `X-Note-Date` (where it is placed in the feed: a past date backdates it, a future one schedules it), `X-Note-Draft` (`true`: a draft, which readers do not see until it is published). 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 ``. Several pictures may have the same file name (a phone calls every photo `image.jpg`): each is stored, and they are appended, but a text that refers to such a name is 400. 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, `X-Note-Tags` on every note, `X-Note-Date` on the text note (its pictures take the milliseconds just before it); 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,
|
|
@@ -46,6 +46,10 @@ export type Note = {
|
|
|
46
46
|
* Present, and true, when the note's date is after now: it is stored, and readers see it from its date on. Absent for every other note
|
|
47
47
|
*/
|
|
48
48
|
scheduled?: true;
|
|
49
|
+
/**
|
|
50
|
+
* Present, and true, for a draft: only whoever can post to the feed sees it; readers do not, until it is published (PATCH `draft: false`). Absent for every other note
|
|
51
|
+
*/
|
|
52
|
+
draft?: true;
|
|
49
53
|
/**
|
|
50
54
|
* The note's page in the web UI
|
|
51
55
|
*/
|
|
@@ -95,6 +99,10 @@ export type Created = {
|
|
|
95
99
|
* 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
|
|
96
100
|
*/
|
|
97
101
|
file_url: string | null;
|
|
102
|
+
/**
|
|
103
|
+
* Present, and true, when the note was stored as a draft (`X-Note-Draft: true`): readers do not see it, or its file, until it is published
|
|
104
|
+
*/
|
|
105
|
+
draft?: true;
|
|
98
106
|
};
|
|
99
107
|
/**
|
|
100
108
|
* The note the post is about: its text note, or with no `text` part its first picture
|
|
@@ -121,6 +129,10 @@ export type Posted = {
|
|
|
121
129
|
* 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
|
|
122
130
|
*/
|
|
123
131
|
file_url: string | null;
|
|
132
|
+
/**
|
|
133
|
+
* Present, and true, when the note was stored as a draft (`X-Note-Draft: true`): readers do not see it, or its file, until it is published
|
|
134
|
+
*/
|
|
135
|
+
draft?: true;
|
|
124
136
|
/**
|
|
125
137
|
* A multipart request's pictures, one per `file` part, in their order; absent for a raw body
|
|
126
138
|
*/
|
|
@@ -171,6 +183,10 @@ export type NoteEdited = {
|
|
|
171
183
|
* Present, and true, when the note's date is after now: it is stored, and readers see it from its date on. Absent for every other note
|
|
172
184
|
*/
|
|
173
185
|
scheduled?: true;
|
|
186
|
+
/**
|
|
187
|
+
* Present, and true, for a draft: only whoever can post to the feed sees it; readers do not, until it is published (PATCH `draft: false`). Absent for every other note
|
|
188
|
+
*/
|
|
189
|
+
draft?: true;
|
|
174
190
|
/**
|
|
175
191
|
* The note's page in the web UI
|
|
176
192
|
*/
|
|
@@ -210,7 +226,7 @@ export type Error = {
|
|
|
210
226
|
/**
|
|
211
227
|
* Stable machine-readable code; absent only on a 500
|
|
212
228
|
*/
|
|
213
|
-
code?: 'invalid_feed' | 'reserved_feed' | 'auth' | 'rate_limited' | 'too_many_attempts' | 'feed_limit' | 'note_limit' | 'image_limit' | 'images_off' | 'license_required' | 'empty_note' | 'too_large' | 'unsupported_type' | 'invalid_body' | 'invalid_request' | 'not_found' | 'feed_exists' | 'taken' | 'removed' | 'blocked' | 'unreadable' | 'unavailable' | 'busy';
|
|
229
|
+
code?: 'invalid_feed' | 'reserved_feed' | 'auth' | 'rate_limited' | 'too_many_attempts' | 'feed_limit' | 'note_limit' | 'image_limit' | 'images_off' | 'license_required' | 'empty_note' | 'too_large' | 'unsupported_type' | 'invalid_body' | 'invalid_request' | 'not_found' | 'feed_exists' | 'taken' | 'title_image' | 'removed' | 'blocked' | 'unreadable' | 'unavailable' | 'busy';
|
|
214
230
|
};
|
|
215
231
|
export type NoteMeta = {
|
|
216
232
|
/**
|
|
@@ -229,6 +245,10 @@ export type NoteMeta = {
|
|
|
229
245
|
* An ISO 8601 date and time with its offset (`2026-10-01T09:30:00Z`, `2026-10-01T11:30:00+02:00`) or a date alone (midnight UTC). When the note is placed in the feed, from 1970 to 9999. A time after now schedules it: readers see it from then on. The note's attachments move with it.
|
|
230
246
|
*/
|
|
231
247
|
date?: string;
|
|
248
|
+
/**
|
|
249
|
+
* true makes the note a draft, which readers do not see; false publishes it. Its attachments follow (an attachment's own state can't be set: 400), and its date stays: a past date places it there, a future one schedules it. A note whose picture is the feed's title image cannot become a draft (409, `title_image`)
|
|
250
|
+
*/
|
|
251
|
+
draft?: boolean;
|
|
232
252
|
};
|
|
233
253
|
export type PasswordJson = {
|
|
234
254
|
/**
|
|
@@ -483,6 +503,10 @@ export type PostNoteData = {
|
|
|
483
503
|
* An ISO 8601 date and time with its offset (`2026-10-01T09:30:00Z`, `2026-10-01T11:30:00+02:00`) or a date alone (midnight UTC). When the note is placed in the feed, from 1970 to 9999. A time after now schedules it: readers see it from then on. Empty is now.
|
|
484
504
|
*/
|
|
485
505
|
'X-Note-Date'?: string;
|
|
506
|
+
/**
|
|
507
|
+
* `true` stores the note, and its pictures, as a draft: only whoever can post to the feed sees it, readers do not until it is published. Left out or `false`: published
|
|
508
|
+
*/
|
|
509
|
+
'X-Note-Draft'?: 'true' | 'false';
|
|
486
510
|
};
|
|
487
511
|
path: {
|
|
488
512
|
/**
|
|
@@ -495,7 +519,7 @@ export type PostNoteData = {
|
|
|
495
519
|
};
|
|
496
520
|
export type PostNoteErrors = {
|
|
497
521
|
/**
|
|
498
|
-
* Invalid or reserved feed name; a blank note; a bad title, alt text, tags or `X-Note-
|
|
522
|
+
* Invalid or reserved feed name; a blank note; a bad title, alt text, tags, `X-Note-Date` or `X-Note-Draft`; `X-Note-Created` (the header's name before 0.28.0); a new password that is not printable ASCII; a license key that is none; a multipart body with an unexpected part, no `text` and no `file`, more than 10 files, a bad file name, a text that refers to a file name given twice, a text sent with pictures that takes too long to read (`NOTEFEED_PARSE_TIMEOUT_MS`), or `X-Note-Alt` / `X-Note-Name`
|
|
499
523
|
*/
|
|
500
524
|
400: Error;
|
|
501
525
|
/**
|
|
@@ -676,7 +700,7 @@ export type PatchNoteData = {
|
|
|
676
700
|
};
|
|
677
701
|
export type PatchNoteErrors = {
|
|
678
702
|
/**
|
|
679
|
-
* Invalid or reserved feed name; nothing to change; a bad title, alt text, tag or
|
|
703
|
+
* Invalid or reserved feed name; nothing to change; a bad title, alt text, tag, date or draft; too many tags; alt for a note that has none; bad JSON
|
|
680
704
|
*/
|
|
681
705
|
400: Error;
|
|
682
706
|
/**
|
|
@@ -687,6 +711,10 @@ export type PatchNoteErrors = {
|
|
|
687
711
|
* No such note
|
|
688
712
|
*/
|
|
689
713
|
404: Error;
|
|
714
|
+
/**
|
|
715
|
+
* The note, or a picture posted with it, is the feed's title image, so it cannot become a draft (`title_image`)
|
|
716
|
+
*/
|
|
717
|
+
409: Error;
|
|
690
718
|
/**
|
|
691
719
|
* Content-Type is not application/json
|
|
692
720
|
*/
|
package/package.json
CHANGED