notefeed 0.29.0 → 0.31.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 +1 -1
- package/dist/client.d.ts +22 -1
- package/dist/client.js +25 -3
- package/dist/generated/client/utils.gen.d.ts +2 -2
- package/dist/generated/core/pathSerializer.gen.d.ts +3 -3
- package/dist/generated/index.d.ts +2 -2
- package/dist/generated/index.js +1 -1
- package/dist/generated/sdk.gen.d.ts +27 -3
- package/dist/generated/sdk.gen.js +55 -2
- package/dist/generated/types.gen.d.ts +246 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,6 +33,6 @@ A posted note can be changed or removed: `await client.edit(id, content)` replac
|
|
|
33
33
|
|
|
34
34
|
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.
|
|
35
35
|
|
|
36
|
-
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, a picture that is too large is a `NoteTooLargeError`, and an instance that takes no pictures (`NOTEFEED_IMAGE_UPLOADS=0`) answers every picture with an `ImagesOffError`. The server checks the bytes against the declared type. `await client.update(id, { title, alt, tags, date })` changes a note's title, a picture's alt text, a note's tags (the whole list; `notefeed update <id> --tags a,b`) or its date, 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.
|
|
36
|
+
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, a picture that is too large is a `NoteTooLargeError`, and an instance that takes no pictures (`NOTEFEED_IMAGE_UPLOADS=0`) answers every picture with an `ImagesOffError`. The server checks the bytes against the declared type. `await client.update(id, { title, alt, tags, date })` changes a note's title, a picture's alt text, a note's tags (the whole list; `notefeed update <id> --tags a,b`) or its date, 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. Send pictures full size (up to 10 MiB by default): the server stores each one turned upright, at most 2560 px on its long side and without metadata such as EXIF or GPS position, and a busy server answers a `RateLimitedError` with `retryAfter`. Pictures are public to anyone with the feed's read link.
|
|
37
37
|
|
|
38
38
|
Full documentation: https://docs.notefeed.me/integrations/clients/
|
package/dist/client.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export declare class ConfigError extends NotefeedError {
|
|
|
29
29
|
/** Missing or wrong password on a locked instance. */
|
|
30
30
|
export declare class AuthError extends NotefeedError {
|
|
31
31
|
}
|
|
32
|
-
/** Too many posts or wrong passwords. `retryAfter` is the wait in seconds, or null if none was given. */
|
|
32
|
+
/** Too many posts or wrong passwords, or (code `busy`, 503) the server is busy processing other images. `retryAfter` is the wait in seconds, or null if none was given. */
|
|
33
33
|
export declare class RateLimitedError extends NotefeedError {
|
|
34
34
|
readonly retryAfter: number | null;
|
|
35
35
|
constructor(message: string, status: number | null, code: ErrorCode | null, retryAfter: number | null);
|
|
@@ -142,6 +142,27 @@ export declare class Client {
|
|
|
142
142
|
feed?: string;
|
|
143
143
|
feedPassword?: string;
|
|
144
144
|
}): Promise<void>;
|
|
145
|
+
/** Create the feed without posting a note, to reserve its name: `password` protects it from its first moment, `readId` gives it that read link. Where licenses are sold `licenseKey` is required and goes on the new feed. A feed that exists is refused (409). */
|
|
146
|
+
createFeed(options?: {
|
|
147
|
+
feed?: string;
|
|
148
|
+
password?: string;
|
|
149
|
+
licenseKey?: string;
|
|
150
|
+
readId?: string;
|
|
151
|
+
}): Promise<Feed>;
|
|
152
|
+
/** For a lost password, only on an instance that sells licenses: the key of the license on the feed proves ownership instead of the current password. `password` becomes the feed's password (needs an active license); left out or empty, the password is removed, which a lapsed license's key may do too. A key that is not the feed's license is refused and counts as a failed attempt. */
|
|
153
|
+
recoverFeedPassword(key: string, password?: string, options?: {
|
|
154
|
+
feed?: string;
|
|
155
|
+
}): Promise<void>;
|
|
156
|
+
/** Set the feed's title image: `content` the image's bytes, `type` its media type (image/png, image/jpeg, image/gif, image/webp). It is the feed's own image, in no list, so no post; a previous one set this way is deleted. Same options as post(). */
|
|
157
|
+
setFeedImage(content: Uint8Array, type: string, options?: {
|
|
158
|
+
feed?: string;
|
|
159
|
+
feedPassword?: string;
|
|
160
|
+
}): Promise<Feed>;
|
|
161
|
+
/** Remove the feed's title image; one set with setFeedImage is deleted. Same options as post(). */
|
|
162
|
+
removeFeedImage(options?: {
|
|
163
|
+
feed?: string;
|
|
164
|
+
feedPassword?: string;
|
|
165
|
+
}): Promise<Feed>;
|
|
145
166
|
/** Delete the feed with all its notes, settings and password, for good; its name is free again. Same options as post(). */
|
|
146
167
|
deleteFeed(options?: {
|
|
147
168
|
feed?: string;
|
package/dist/client.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* OpenAPI description (./generated, `npm run generate` in the repo). No runtime dependencies.
|
|
4
4
|
*/
|
|
5
5
|
import { createClient, createConfig } from "./generated/client/index.js";
|
|
6
|
-
import { changeFeedPassword, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getReadNote, listNotes, listReadNotes, patchNote, postNote, putFeedLicense, updateFeed } from "./generated/sdk.gen.js";
|
|
6
|
+
import { changeFeedPassword, createFeed, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getReadNote, listNotes, listReadNotes, patchNote, postNote, putFeedLicense, recoverFeedPassword, removeFeedImage, setFeedImage, updateFeed } from "./generated/sdk.gen.js";
|
|
7
7
|
/** Any failure talking to notefeed. `status` and `code` are null when there was no API answer. */
|
|
8
8
|
export class NotefeedError extends Error {
|
|
9
9
|
status;
|
|
@@ -21,7 +21,7 @@ export class ConfigError extends NotefeedError {
|
|
|
21
21
|
/** Missing or wrong password on a locked instance. */
|
|
22
22
|
export class AuthError extends NotefeedError {
|
|
23
23
|
}
|
|
24
|
-
/** Too many posts or wrong passwords. `retryAfter` is the wait in seconds, or null if none was given. */
|
|
24
|
+
/** Too many posts or wrong passwords, or (code `busy`, 503) the server is busy processing other images. `retryAfter` is the wait in seconds, or null if none was given. */
|
|
25
25
|
export class RateLimitedError extends NotefeedError {
|
|
26
26
|
retryAfter;
|
|
27
27
|
constructor(message, status, code, retryAfter) {
|
|
@@ -227,6 +227,28 @@ export class Client {
|
|
|
227
227
|
const feed = this.feedFor(options.feed);
|
|
228
228
|
await this.call(changeFeedPassword({ client: this.api, path: { feed }, body: { password }, ...this.opts(options.feedPassword) }));
|
|
229
229
|
}
|
|
230
|
+
/** Create the feed without posting a note, to reserve its name: `password` protects it from its first moment, `readId` gives it that read link. Where licenses are sold `licenseKey` is required and goes on the new feed. A feed that exists is refused (409). */
|
|
231
|
+
async createFeed(options = {}) {
|
|
232
|
+
const feed = this.feedFor(options.feed);
|
|
233
|
+
const body = { ...(options.password ? { password: options.password } : {}), ...(options.licenseKey ? { license_key: options.licenseKey } : {}), ...(options.readId ? { read_id: options.readId } : {}) };
|
|
234
|
+
return this.call(createFeed({ client: this.api, path: { feed }, body, signal: AbortSignal.timeout(this.timeoutMs) }));
|
|
235
|
+
}
|
|
236
|
+
/** For a lost password, only on an instance that sells licenses: the key of the license on the feed proves ownership instead of the current password. `password` becomes the feed's password (needs an active license); left out or empty, the password is removed, which a lapsed license's key may do too. A key that is not the feed's license is refused and counts as a failed attempt. */
|
|
237
|
+
async recoverFeedPassword(key, password = "", options = {}) {
|
|
238
|
+
const feed = this.feedFor(options.feed);
|
|
239
|
+
await this.call(recoverFeedPassword({ client: this.api, path: { feed }, body: { key, password }, signal: AbortSignal.timeout(this.timeoutMs) })); // the key instead of the (lost) feed password
|
|
240
|
+
}
|
|
241
|
+
/** Set the feed's title image: `content` the image's bytes, `type` its media type (image/png, image/jpeg, image/gif, image/webp). It is the feed's own image, in no list, so no post; a previous one set this way is deleted. Same options as post(). */
|
|
242
|
+
async setFeedImage(content, type, options = {}) {
|
|
243
|
+
const feed = this.feedFor(options.feed);
|
|
244
|
+
const opts = this.opts(options.feedPassword);
|
|
245
|
+
return this.call(setFeedImage({ client: this.api, path: { feed }, body: new Blob([content], { type }), ...opts, headers: { ...opts.headers, "Content-Type": type } }));
|
|
246
|
+
}
|
|
247
|
+
/** Remove the feed's title image; one set with setFeedImage is deleted. Same options as post(). */
|
|
248
|
+
async removeFeedImage(options = {}) {
|
|
249
|
+
const feed = this.feedFor(options.feed);
|
|
250
|
+
return this.call(removeFeedImage({ client: this.api, path: { feed }, ...this.opts(options.feedPassword) }));
|
|
251
|
+
}
|
|
230
252
|
/** Delete the feed with all its notes, settings and password, for good; its name is free again. Same options as post(). */
|
|
231
253
|
async deleteFeed(options = {}) {
|
|
232
254
|
const feed = this.feedFor(options.feed);
|
|
@@ -293,7 +315,7 @@ export class Client {
|
|
|
293
315
|
const raw = typeof error === "string" ? error : isObject(error) && Object.keys(error).length ? JSON.stringify(error) : "";
|
|
294
316
|
message = `HTTP ${response.status}: ${raw.slice(0, 200).replace(/\s+/g, " ").trim()}`.replace(/: $/, "");
|
|
295
317
|
}
|
|
296
|
-
if (code === "rate_limited" || code === "too_many_attempts" || response.status === 429) {
|
|
318
|
+
if (code === "rate_limited" || code === "too_many_attempts" || code === "busy" || response.status === 429) {
|
|
297
319
|
const retry = response.headers.get("retry-after")?.trim() ?? "";
|
|
298
320
|
throw new RateLimitedError(message, response.status, code, /^\d+$/.test(retry) ? Number(retry) : null);
|
|
299
321
|
}
|
|
@@ -4,13 +4,13 @@ export declare const createQuerySerializer: <T = unknown>({ parameters, ...args
|
|
|
4
4
|
/**
|
|
5
5
|
* Infers parseAs value from provided Content-Type header.
|
|
6
6
|
*/
|
|
7
|
-
export declare const getParseAs: (contentType: string | null) => Exclude<Config[
|
|
7
|
+
export declare const getParseAs: (contentType: string | null) => Exclude<Config['parseAs'], 'auto'>;
|
|
8
8
|
export declare function setAuthParams(options: Pick<RequestOptions, 'auth' | 'query' | 'security'> & {
|
|
9
9
|
headers: Headers;
|
|
10
10
|
}): Promise<void>;
|
|
11
11
|
export declare const buildUrl: Client['buildUrl'];
|
|
12
12
|
export declare const mergeConfigs: (a: Config, b: Config) => Config;
|
|
13
|
-
export declare const mergeHeaders: (...headers: Array<Required<Config>[
|
|
13
|
+
export declare const mergeHeaders: (...headers: Array<Required<Config>['headers'] | undefined>) => Headers;
|
|
14
14
|
type ErrInterceptor<Err, Res, Req, Options> = (error: Err,
|
|
15
15
|
/** response may be undefined due to a network error where no response object is produced */
|
|
16
16
|
response: Res | undefined,
|
|
@@ -19,9 +19,9 @@ type ObjectSeparatorStyle = ObjectStyle | MatrixStyle;
|
|
|
19
19
|
interface SerializePrimitiveParam extends SerializePrimitiveOptions {
|
|
20
20
|
value: string;
|
|
21
21
|
}
|
|
22
|
-
export declare const separatorArrayExplode: (style: ArraySeparatorStyle) =>
|
|
23
|
-
export declare const separatorArrayNoExplode: (style: ArraySeparatorStyle) =>
|
|
24
|
-
export declare const separatorObjectExplode: (style: ObjectSeparatorStyle) =>
|
|
22
|
+
export declare const separatorArrayExplode: (style: ArraySeparatorStyle) => '.' | ';' | ',' | '&';
|
|
23
|
+
export declare const separatorArrayNoExplode: (style: ArraySeparatorStyle) => ',' | '|' | '%20';
|
|
24
|
+
export declare const separatorObjectExplode: (style: ObjectSeparatorStyle) => '.' | ';' | ',' | '&';
|
|
25
25
|
export declare const serializeArrayParam: ({ allowReserved, explode, name, style, value, }: SerializeOptions<ArraySeparatorStyle> & {
|
|
26
26
|
value: unknown[];
|
|
27
27
|
}) => string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { changeFeedPassword, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getOpenApi, getReadFeed, getReadNote, listNotes, listReadNotes, type Options, patchNote, postNote, putFeedLicense, removeFeedPassword, updateFeed } from './sdk.gen.js';
|
|
2
|
-
export type { ChangeFeedPasswordData, ChangeFeedPasswordError, ChangeFeedPasswordErrors, ChangeFeedPasswordResponse, ChangeFeedPasswordResponses, ClientOptions, Created, DeleteFeedData, DeleteFeedError, DeleteFeedErrors, DeleteFeedLicenseData, DeleteFeedLicenseError, DeleteFeedLicenseErrors, DeleteFeedLicenseResponse, DeleteFeedLicenseResponses, DeleteFeedResponse, DeleteFeedResponses, DeleteNoteData, DeleteNoteError, DeleteNoteErrors, DeleteNoteResponse, DeleteNoteResponses, EditNoteData, EditNoteError, EditNoteErrors, EditNoteResponse, EditNoteResponses, Error, Feed, FeedSettings, FreeTier, GetFeedData, GetFeedError, GetFeedErrors, GetFeedResponse, GetFeedResponses, GetNoteData, GetNoteError, GetNoteErrors, GetNoteResponse, GetNoteResponses, GetOpenApiData, GetOpenApiResponse, GetOpenApiResponses, GetReadFeedData, GetReadFeedError, GetReadFeedErrors, GetReadFeedResponse, GetReadFeedResponses, GetReadNoteData, GetReadNoteError, GetReadNoteErrors, GetReadNoteResponse, GetReadNoteResponses, LicenseKey, 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, PutFeedLicenseData, PutFeedLicenseError, PutFeedLicenseErrors, PutFeedLicenseResponse, PutFeedLicenseResponses, ReadFeed, RemoveFeedPasswordData, RemoveFeedPasswordError, RemoveFeedPasswordErrors, RemoveFeedPasswordResponse, RemoveFeedPasswordResponses, UpdateFeedData, UpdateFeedError, UpdateFeedErrors, UpdateFeedResponse, UpdateFeedResponses } from './types.gen.js';
|
|
1
|
+
export { changeFeedPassword, createFeed, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getOpenApi, getReadFeed, getReadNote, listNotes, listReadNotes, type Options, patchNote, postNote, putFeedLicense, recoverFeedPassword, removeFeedImage, removeFeedPassword, setFeedImage, updateFeed } from './sdk.gen.js';
|
|
2
|
+
export type { ChangeFeedPasswordData, ChangeFeedPasswordError, ChangeFeedPasswordErrors, ChangeFeedPasswordResponse, ChangeFeedPasswordResponses, ClientOptions, Created, CreateFeedData, CreateFeedError, CreateFeedErrors, CreateFeedJson, CreateFeedResponse, CreateFeedResponses, DeleteFeedData, DeleteFeedError, DeleteFeedErrors, DeleteFeedLicenseData, DeleteFeedLicenseError, DeleteFeedLicenseErrors, DeleteFeedLicenseResponse, DeleteFeedLicenseResponses, DeleteFeedResponse, DeleteFeedResponses, DeleteNoteData, DeleteNoteError, DeleteNoteErrors, DeleteNoteResponse, DeleteNoteResponses, EditNoteData, EditNoteError, EditNoteErrors, EditNoteResponse, EditNoteResponses, Error, Feed, FeedSettings, FreeTier, GetFeedData, GetFeedError, GetFeedErrors, GetFeedResponse, GetFeedResponses, GetNoteData, GetNoteError, GetNoteErrors, GetNoteResponse, GetNoteResponses, GetOpenApiData, GetOpenApiResponse, GetOpenApiResponses, GetReadFeedData, GetReadFeedError, GetReadFeedErrors, GetReadFeedResponse, GetReadFeedResponses, GetReadNoteData, GetReadNoteError, GetReadNoteErrors, GetReadNoteResponse, GetReadNoteResponses, LicenseKey, 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, PutFeedLicenseData, PutFeedLicenseError, PutFeedLicenseErrors, PutFeedLicenseResponse, PutFeedLicenseResponses, ReadFeed, RecoverFeedPasswordData, RecoverFeedPasswordError, RecoverFeedPasswordErrors, RecoverFeedPasswordResponse, RecoverFeedPasswordResponses, RecoveryJson, RemoveFeedImageData, RemoveFeedImageError, RemoveFeedImageErrors, RemoveFeedImageResponse, RemoveFeedImageResponses, RemoveFeedPasswordData, RemoveFeedPasswordError, RemoveFeedPasswordErrors, RemoveFeedPasswordResponse, RemoveFeedPasswordResponses, SetFeedImageData, SetFeedImageError, SetFeedImageErrors, SetFeedImageResponse, SetFeedImageResponses, UpdateFeedData, UpdateFeedError, UpdateFeedErrors, UpdateFeedResponse, UpdateFeedResponses } from './types.gen.js';
|
package/dist/generated/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
|
-
export { changeFeedPassword, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getOpenApi, getReadFeed, getReadNote, listNotes, listReadNotes, patchNote, postNote, putFeedLicense, removeFeedPassword, updateFeed } from './sdk.gen.js';
|
|
2
|
+
export { changeFeedPassword, createFeed, deleteFeed, deleteFeedLicense, deleteNote, editNote, getFeed, getNote, getOpenApi, getReadFeed, getReadNote, listNotes, listReadNotes, patchNote, postNote, putFeedLicense, recoverFeedPassword, removeFeedImage, removeFeedPassword, setFeedImage, updateFeed } from './sdk.gen.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Client, ClientMeta, Options as Options2, RequestResult, TDataShape } from './client/index.js';
|
|
2
|
-
import type { ChangeFeedPasswordData, ChangeFeedPasswordErrors, ChangeFeedPasswordResponses, DeleteFeedData, DeleteFeedErrors, DeleteFeedLicenseData, DeleteFeedLicenseErrors, DeleteFeedLicenseResponses, DeleteFeedResponses, DeleteNoteData, DeleteNoteErrors, DeleteNoteResponses, EditNoteData, EditNoteErrors, EditNoteResponses, GetFeedData, GetFeedErrors, GetFeedResponses, GetNoteData, GetNoteErrors, GetNoteResponses, GetOpenApiData, GetOpenApiResponses, GetReadFeedData, GetReadFeedErrors, GetReadFeedResponses, GetReadNoteData, GetReadNoteErrors, GetReadNoteResponses, ListNotesData, ListNotesErrors, ListNotesResponses, ListReadNotesData, ListReadNotesErrors, ListReadNotesResponses, PatchNoteData, PatchNoteErrors, PatchNoteResponses, PostNoteData, PostNoteErrors, PostNoteResponses, PutFeedLicenseData, PutFeedLicenseErrors, PutFeedLicenseResponses, RemoveFeedPasswordData, RemoveFeedPasswordErrors, RemoveFeedPasswordResponses, UpdateFeedData, UpdateFeedErrors, UpdateFeedResponses } from './types.gen.js';
|
|
2
|
+
import type { ChangeFeedPasswordData, ChangeFeedPasswordErrors, ChangeFeedPasswordResponses, CreateFeedData, CreateFeedErrors, CreateFeedResponses, DeleteFeedData, DeleteFeedErrors, DeleteFeedLicenseData, DeleteFeedLicenseErrors, DeleteFeedLicenseResponses, DeleteFeedResponses, DeleteNoteData, DeleteNoteErrors, DeleteNoteResponses, EditNoteData, EditNoteErrors, EditNoteResponses, GetFeedData, GetFeedErrors, GetFeedResponses, GetNoteData, GetNoteErrors, GetNoteResponses, GetOpenApiData, GetOpenApiResponses, GetReadFeedData, GetReadFeedErrors, GetReadFeedResponses, GetReadNoteData, GetReadNoteErrors, GetReadNoteResponses, ListNotesData, ListNotesErrors, ListNotesResponses, ListReadNotesData, ListReadNotesErrors, ListReadNotesResponses, PatchNoteData, PatchNoteErrors, PatchNoteResponses, PostNoteData, PostNoteErrors, PostNoteResponses, PutFeedLicenseData, PutFeedLicenseErrors, PutFeedLicenseResponses, RecoverFeedPasswordData, RecoverFeedPasswordErrors, RecoverFeedPasswordResponses, RemoveFeedImageData, RemoveFeedImageErrors, RemoveFeedImageResponses, RemoveFeedPasswordData, RemoveFeedPasswordErrors, RemoveFeedPasswordResponses, SetFeedImageData, SetFeedImageErrors, SetFeedImageResponses, UpdateFeedData, UpdateFeedErrors, UpdateFeedResponses } from './types.gen.js';
|
|
3
3
|
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options2<TData, ThrowOnError, TResponse> & {
|
|
4
4
|
/**
|
|
5
5
|
* You can provide a client instance returned by `createClient()` instead of
|
|
@@ -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
|
|
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.
|
|
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, alt text or tags 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.
|
|
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). 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`. Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title, alt text or tags 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 ``. 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. 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
|
/**
|
|
@@ -59,12 +59,30 @@ export declare const deleteFeed: <ThrowOnError extends boolean = false>(options:
|
|
|
59
59
|
* The title and description, the title image, whether the feed is protected, and its read link (null while it has no notes). A feed exists once its first note is posted.
|
|
60
60
|
*/
|
|
61
61
|
export declare const getFeed: <ThrowOnError extends boolean = false>(options: Options<GetFeedData, ThrowOnError>) => RequestResult<GetFeedResponses, GetFeedErrors, ThrowOnError>;
|
|
62
|
+
/**
|
|
63
|
+
* Create a feed without posting a note
|
|
64
|
+
*
|
|
65
|
+
* Reserves the feed name now (ADR 0047): with a password it is protected from its first moment, with a read id it gets that read link. Where licenses are sold a license key is required and goes on the new feed; free feeds start with their first note. A feed that exists is 409. Counts against the post rate limit and the instance's feed cap, like a first post. After it, change the title and description with updateFeed.
|
|
66
|
+
*/
|
|
67
|
+
export declare const createFeed: <ThrowOnError extends boolean = false>(options: Options<CreateFeedData, ThrowOnError>) => RequestResult<CreateFeedResponses, CreateFeedErrors, ThrowOnError>;
|
|
62
68
|
/**
|
|
63
69
|
* Change a feed's settings
|
|
64
70
|
*
|
|
65
71
|
* 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
72
|
*/
|
|
67
73
|
export declare const updateFeed: <ThrowOnError extends boolean = false>(options: Options<UpdateFeedData, ThrowOnError>) => RequestResult<UpdateFeedResponses, UpdateFeedErrors, ThrowOnError>;
|
|
74
|
+
/**
|
|
75
|
+
* Remove the feed's title image
|
|
76
|
+
*
|
|
77
|
+
* The feed has no title image afterwards. One uploaded as the feed's own (setFeedImage) is deleted; a posted image that was the title image stays a post.
|
|
78
|
+
*/
|
|
79
|
+
export declare const removeFeedImage: <ThrowOnError extends boolean = false>(options: Options<RemoveFeedImageData, ThrowOnError>) => RequestResult<RemoveFeedImageResponses, RemoveFeedImageErrors, ThrowOnError>;
|
|
80
|
+
/**
|
|
81
|
+
* Set the feed's title image
|
|
82
|
+
*
|
|
83
|
+
* Uploads the image (its bytes, of the type `Content-Type` declares) as the feed's own title image: it is shown in the feed's header and stored as an image note, but in no list (timeline, RSS, the read API, counts), so it is no post. A previous title image uploaded this way is deleted; a posted image picked with `updateFeed`'s `image` stays a post. The same checks as posting a picture apply. The feed must exist. 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`.
|
|
84
|
+
*/
|
|
85
|
+
export declare const setFeedImage: <ThrowOnError extends boolean = false>(options: Options<SetFeedImageData, ThrowOnError>) => RequestResult<SetFeedImageResponses, SetFeedImageErrors, ThrowOnError>;
|
|
68
86
|
/**
|
|
69
87
|
* Remove a feed's password
|
|
70
88
|
*
|
|
@@ -77,6 +95,12 @@ export declare const removeFeedPassword: <ThrowOnError extends boolean = false>(
|
|
|
77
95
|
* On a protected feed: changes the password, with the current one in `X-Feed-Password`. On an open feed: sets one, with no current password, for whoever calls it. An open feed's name is all that protects it, so whoever knows the name may claim the feed this way. From then on everyone who posts to the feed, reads it by its name or changes it needs the password; the read link and RSS stay open.
|
|
78
96
|
*/
|
|
79
97
|
export declare const changeFeedPassword: <ThrowOnError extends boolean = false>(options: Options<ChangeFeedPasswordData, ThrowOnError>) => RequestResult<ChangeFeedPasswordResponses, ChangeFeedPasswordErrors, ThrowOnError>;
|
|
98
|
+
/**
|
|
99
|
+
* Recover a feed's password with its license key
|
|
100
|
+
*
|
|
101
|
+
* Only on an instance that sells licenses (404 elsewhere). For a lost password: the key of the license on this feed proves ownership instead of the current password (ADR 0037). With a new password the feed gets it (needs an active license, like any password change); with none, or an empty one, the password is removed, which a lapsed license's key may do too. A key that is not this feed's license is 401 and counts as a failed attempt, like a wrong password; a bad new password is refused before the key is tried.
|
|
102
|
+
*/
|
|
103
|
+
export declare const recoverFeedPassword: <ThrowOnError extends boolean = false>(options: Options<RecoverFeedPasswordData, ThrowOnError>) => RequestResult<RecoverFeedPasswordResponses, RecoverFeedPasswordErrors, ThrowOnError>;
|
|
80
104
|
/**
|
|
81
105
|
* Take a feed's license off
|
|
82
106
|
*
|
|
@@ -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
|
|
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.
|
|
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, alt text or tags 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.
|
|
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). 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`. Id, creation time and metadata stay: the title of a markdown note without one set follows the new text. Change the title, alt text or tags 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 ``. 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. 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,
|
|
@@ -92,6 +92,20 @@ export const getFeed = (options) => (options.client ?? client).get({
|
|
|
92
92
|
url: '/api/v1/feeds/{feed}',
|
|
93
93
|
...options
|
|
94
94
|
});
|
|
95
|
+
/**
|
|
96
|
+
* Create a feed without posting a note
|
|
97
|
+
*
|
|
98
|
+
* Reserves the feed name now (ADR 0047): with a password it is protected from its first moment, with a read id it gets that read link. Where licenses are sold a license key is required and goes on the new feed; free feeds start with their first note. A feed that exists is 409. Counts against the post rate limit and the instance's feed cap, like a first post. After it, change the title and description with updateFeed.
|
|
99
|
+
*/
|
|
100
|
+
export const createFeed = (options) => (options.client ?? client).post({
|
|
101
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
102
|
+
url: '/api/v1/feeds/{feed}',
|
|
103
|
+
...options,
|
|
104
|
+
headers: {
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
...options.headers
|
|
107
|
+
}
|
|
108
|
+
});
|
|
95
109
|
/**
|
|
96
110
|
* Change a feed's settings
|
|
97
111
|
*
|
|
@@ -106,6 +120,31 @@ export const updateFeed = (options) => (options.client ?? client).put({
|
|
|
106
120
|
...options.headers
|
|
107
121
|
}
|
|
108
122
|
});
|
|
123
|
+
/**
|
|
124
|
+
* Remove the feed's title image
|
|
125
|
+
*
|
|
126
|
+
* The feed has no title image afterwards. One uploaded as the feed's own (setFeedImage) is deleted; a posted image that was the title image stays a post.
|
|
127
|
+
*/
|
|
128
|
+
export const removeFeedImage = (options) => (options.client ?? client).delete({
|
|
129
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
130
|
+
url: '/api/v1/feeds/{feed}/image',
|
|
131
|
+
...options
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* Set the feed's title image
|
|
135
|
+
*
|
|
136
|
+
* Uploads the image (its bytes, of the type `Content-Type` declares) as the feed's own title image: it is shown in the feed's header and stored as an image note, but in no list (timeline, RSS, the read API, counts), so it is no post. A previous title image uploaded this way is deleted; a posted image picked with `updateFeed`'s `image` stays a post. The same checks as posting a picture apply. The feed must exist. 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`.
|
|
137
|
+
*/
|
|
138
|
+
export const setFeedImage = (options) => (options.client ?? client).put({
|
|
139
|
+
bodySerializer: null,
|
|
140
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
141
|
+
url: '/api/v1/feeds/{feed}/image',
|
|
142
|
+
...options,
|
|
143
|
+
headers: {
|
|
144
|
+
'Content-Type': 'image/png',
|
|
145
|
+
...options.headers
|
|
146
|
+
}
|
|
147
|
+
});
|
|
109
148
|
/**
|
|
110
149
|
* Remove a feed's password
|
|
111
150
|
*
|
|
@@ -130,6 +169,20 @@ export const changeFeedPassword = (options) => (options.client ?? client).put({
|
|
|
130
169
|
...options.headers
|
|
131
170
|
}
|
|
132
171
|
});
|
|
172
|
+
/**
|
|
173
|
+
* Recover a feed's password with its license key
|
|
174
|
+
*
|
|
175
|
+
* Only on an instance that sells licenses (404 elsewhere). For a lost password: the key of the license on this feed proves ownership instead of the current password (ADR 0037). With a new password the feed gets it (needs an active license, like any password change); with none, or an empty one, the password is removed, which a lapsed license's key may do too. A key that is not this feed's license is 401 and counts as a failed attempt, like a wrong password; a bad new password is refused before the key is tried.
|
|
176
|
+
*/
|
|
177
|
+
export const recoverFeedPassword = (options) => (options.client ?? client).post({
|
|
178
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
179
|
+
url: '/api/v1/feeds/{feed}/password/recover',
|
|
180
|
+
...options,
|
|
181
|
+
headers: {
|
|
182
|
+
'Content-Type': 'application/json',
|
|
183
|
+
...options.headers
|
|
184
|
+
}
|
|
185
|
+
});
|
|
133
186
|
/**
|
|
134
187
|
* Take a feed's license off
|
|
135
188
|
*
|
|
@@ -210,7 +210,7 @@ export type Error = {
|
|
|
210
210
|
/**
|
|
211
211
|
* Stable machine-readable code; absent only on a 500
|
|
212
212
|
*/
|
|
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';
|
|
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';
|
|
214
214
|
};
|
|
215
215
|
export type NoteMeta = {
|
|
216
216
|
/**
|
|
@@ -236,6 +236,30 @@ export type PasswordJson = {
|
|
|
236
236
|
*/
|
|
237
237
|
password: string;
|
|
238
238
|
};
|
|
239
|
+
export type RecoveryJson = {
|
|
240
|
+
/**
|
|
241
|
+
* The license key on this feed, as the checkout or the receipt gave it
|
|
242
|
+
*/
|
|
243
|
+
key: string;
|
|
244
|
+
/**
|
|
245
|
+
* The new password: 1 to 256 printable ASCII characters, with no space at the start or end. Empty or left out removes the password
|
|
246
|
+
*/
|
|
247
|
+
password?: string;
|
|
248
|
+
};
|
|
249
|
+
export type CreateFeedJson = {
|
|
250
|
+
/**
|
|
251
|
+
* A password that protects the new feed: 1 to 256 printable ASCII characters, with no space at the start or end. Empty or left out: an open feed
|
|
252
|
+
*/
|
|
253
|
+
password?: string;
|
|
254
|
+
/**
|
|
255
|
+
* Where licenses are sold, required: the key of the license to put on the new feed
|
|
256
|
+
*/
|
|
257
|
+
license_key?: string;
|
|
258
|
+
/**
|
|
259
|
+
* The read id to give the feed (3 to 64 characters of a-z, 0-9, - and _); left out: a random one
|
|
260
|
+
*/
|
|
261
|
+
read_id?: string;
|
|
262
|
+
};
|
|
239
263
|
export type LicenseKey = {
|
|
240
264
|
/**
|
|
241
265
|
* The license key, as the checkout or the receipt gave it
|
|
@@ -428,7 +452,7 @@ export type PostNoteData = {
|
|
|
428
452
|
};
|
|
429
453
|
export type PostNoteErrors = {
|
|
430
454
|
/**
|
|
431
|
-
* Invalid or reserved feed name; a blank note; a bad title, alt text, tags or `X-Note-Date`; `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
|
|
455
|
+
* Invalid or reserved feed name; a blank note; a bad title, alt text, tags or `X-Note-Date`; `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`
|
|
432
456
|
*/
|
|
433
457
|
400: Error;
|
|
434
458
|
/**
|
|
@@ -452,7 +476,7 @@ export type PostNoteErrors = {
|
|
|
452
476
|
*/
|
|
453
477
|
410: Error;
|
|
454
478
|
/**
|
|
455
|
-
* 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
|
|
479
|
+
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES or 100 megapixels (each picture of a multipart body too), or a multipart body over 102400 bytes plus 10 images plus 64 KiB, and never over 64 MiB
|
|
456
480
|
*/
|
|
457
481
|
413: Error;
|
|
458
482
|
/**
|
|
@@ -468,7 +492,7 @@ export type PostNoteErrors = {
|
|
|
468
492
|
*/
|
|
469
493
|
451: Error;
|
|
470
494
|
/**
|
|
471
|
-
*
|
|
495
|
+
* `unavailable`: the key service is unreachable, the instance is down for maintenance. `busy`: too many images are being processed at the moment. Either way, try again after Retry-After
|
|
472
496
|
*/
|
|
473
497
|
503: Error;
|
|
474
498
|
/**
|
|
@@ -671,7 +695,7 @@ export type EditNoteData = {
|
|
|
671
695
|
};
|
|
672
696
|
export type EditNoteErrors = {
|
|
673
697
|
/**
|
|
674
|
-
* Invalid or reserved feed name; a blank note; a multipart body with an unexpected part, no `text`, more than 10 files, a bad
|
|
698
|
+
* Invalid or reserved feed name; a blank note; a multipart body with an unexpected part, no `text`, 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`
|
|
675
699
|
*/
|
|
676
700
|
400: Error;
|
|
677
701
|
/**
|
|
@@ -691,7 +715,7 @@ export type EditNoteErrors = {
|
|
|
691
715
|
*/
|
|
692
716
|
404: Error;
|
|
693
717
|
/**
|
|
694
|
-
* 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
|
|
718
|
+
* Markdown over 102400 bytes, or an image over NOTEFEED_MAX_IMAGE_BYTES or 100 megapixels (each picture of a multipart body too), or a multipart body over 102400 bytes plus 10 images plus 64 KiB, and never over 64 MiB
|
|
695
719
|
*/
|
|
696
720
|
413: Error;
|
|
697
721
|
/**
|
|
@@ -707,7 +731,7 @@ export type EditNoteErrors = {
|
|
|
707
731
|
*/
|
|
708
732
|
451: Error;
|
|
709
733
|
/**
|
|
710
|
-
*
|
|
734
|
+
* `unavailable`: the key service is unreachable, the instance is down for maintenance. `busy`: too many images are being processed at the moment. Either way, try again after Retry-After
|
|
711
735
|
*/
|
|
712
736
|
503: Error;
|
|
713
737
|
/**
|
|
@@ -817,6 +841,55 @@ export type GetFeedResponses = {
|
|
|
817
841
|
200: Feed;
|
|
818
842
|
};
|
|
819
843
|
export type GetFeedResponse = GetFeedResponses[keyof GetFeedResponses];
|
|
844
|
+
export type CreateFeedData = {
|
|
845
|
+
body: CreateFeedJson;
|
|
846
|
+
path: {
|
|
847
|
+
/**
|
|
848
|
+
* The feed's name. It is the write key: anyone who knows it can post.
|
|
849
|
+
*/
|
|
850
|
+
feed: string;
|
|
851
|
+
};
|
|
852
|
+
query?: never;
|
|
853
|
+
url: '/api/v1/feeds/{feed}';
|
|
854
|
+
};
|
|
855
|
+
export type CreateFeedErrors = {
|
|
856
|
+
/**
|
|
857
|
+
* Invalid or reserved feed name, bad JSON, a password that is not 1 to 256 printable ASCII characters, with no space at the start or end, a read id that is invalid, or a key that is none
|
|
858
|
+
*/
|
|
859
|
+
400: Error;
|
|
860
|
+
/**
|
|
861
|
+
* A license key is needed to create a feed without a note here, or its license has lapsed (`license_required`)
|
|
862
|
+
*/
|
|
863
|
+
402: Error;
|
|
864
|
+
/**
|
|
865
|
+
* The feed exists already (`feed_exists`), or the read id is taken (`taken`)
|
|
866
|
+
*/
|
|
867
|
+
409: Error;
|
|
868
|
+
/**
|
|
869
|
+
* The operator removed this feed for good (`removed`): its name cannot be used again
|
|
870
|
+
*/
|
|
871
|
+
410: Error;
|
|
872
|
+
/**
|
|
873
|
+
* Too many posts, or wrong keys, from this client
|
|
874
|
+
*/
|
|
875
|
+
429: Error;
|
|
876
|
+
/**
|
|
877
|
+
* The key service is unreachable: the instance is down for maintenance; try again after Retry-After
|
|
878
|
+
*/
|
|
879
|
+
503: Error;
|
|
880
|
+
/**
|
|
881
|
+
* NOTEFEED_MAX_FEEDS reached
|
|
882
|
+
*/
|
|
883
|
+
507: Error;
|
|
884
|
+
};
|
|
885
|
+
export type CreateFeedError = CreateFeedErrors[keyof CreateFeedErrors];
|
|
886
|
+
export type CreateFeedResponses = {
|
|
887
|
+
/**
|
|
888
|
+
* The new feed
|
|
889
|
+
*/
|
|
890
|
+
201: Feed;
|
|
891
|
+
};
|
|
892
|
+
export type CreateFeedResponse = CreateFeedResponses[keyof CreateFeedResponses];
|
|
820
893
|
export type UpdateFeedData = {
|
|
821
894
|
body: FeedSettings;
|
|
822
895
|
headers?: {
|
|
@@ -868,6 +941,127 @@ export type UpdateFeedResponses = {
|
|
|
868
941
|
200: Feed;
|
|
869
942
|
};
|
|
870
943
|
export type UpdateFeedResponse = UpdateFeedResponses[keyof UpdateFeedResponses];
|
|
944
|
+
export type RemoveFeedImageData = {
|
|
945
|
+
body?: never;
|
|
946
|
+
headers?: {
|
|
947
|
+
/**
|
|
948
|
+
* 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.
|
|
949
|
+
*/
|
|
950
|
+
'X-Feed-Password'?: string;
|
|
951
|
+
};
|
|
952
|
+
path: {
|
|
953
|
+
/**
|
|
954
|
+
* The feed's name. It is the write key: anyone who knows it can post.
|
|
955
|
+
*/
|
|
956
|
+
feed: string;
|
|
957
|
+
};
|
|
958
|
+
query?: never;
|
|
959
|
+
url: '/api/v1/feeds/{feed}/image';
|
|
960
|
+
};
|
|
961
|
+
export type RemoveFeedImageErrors = {
|
|
962
|
+
/**
|
|
963
|
+
* Invalid or reserved feed name
|
|
964
|
+
*/
|
|
965
|
+
400: Error;
|
|
966
|
+
/**
|
|
967
|
+
* The instance has a password, or the feed has its own, and it is missing or wrong
|
|
968
|
+
*/
|
|
969
|
+
401: Error;
|
|
970
|
+
/**
|
|
971
|
+
* No such feed
|
|
972
|
+
*/
|
|
973
|
+
404: Error;
|
|
974
|
+
/**
|
|
975
|
+
* Too many posts, or wrong passwords, from this client
|
|
976
|
+
*/
|
|
977
|
+
429: Error;
|
|
978
|
+
/**
|
|
979
|
+
* The key service is unreachable: the instance is down for maintenance; try again after Retry-After
|
|
980
|
+
*/
|
|
981
|
+
503: Error;
|
|
982
|
+
};
|
|
983
|
+
export type RemoveFeedImageError = RemoveFeedImageErrors[keyof RemoveFeedImageErrors];
|
|
984
|
+
export type RemoveFeedImageResponses = {
|
|
985
|
+
/**
|
|
986
|
+
* The feed, without a title image
|
|
987
|
+
*/
|
|
988
|
+
200: Feed;
|
|
989
|
+
};
|
|
990
|
+
export type RemoveFeedImageResponse = RemoveFeedImageResponses[keyof RemoveFeedImageResponses];
|
|
991
|
+
export type SetFeedImageData = {
|
|
992
|
+
/**
|
|
993
|
+
* The note, a file: its bytes, of the type `Content-Type` declares
|
|
994
|
+
*/
|
|
995
|
+
body: Blob | File;
|
|
996
|
+
headers?: {
|
|
997
|
+
/**
|
|
998
|
+
* 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.
|
|
999
|
+
*/
|
|
1000
|
+
'X-Feed-Password'?: string;
|
|
1001
|
+
};
|
|
1002
|
+
path: {
|
|
1003
|
+
/**
|
|
1004
|
+
* The feed's name. It is the write key: anyone who knows it can post.
|
|
1005
|
+
*/
|
|
1006
|
+
feed: string;
|
|
1007
|
+
};
|
|
1008
|
+
query?: never;
|
|
1009
|
+
url: '/api/v1/feeds/{feed}/image';
|
|
1010
|
+
};
|
|
1011
|
+
export type SetFeedImageErrors = {
|
|
1012
|
+
/**
|
|
1013
|
+
* Invalid or reserved feed name
|
|
1014
|
+
*/
|
|
1015
|
+
400: Error;
|
|
1016
|
+
/**
|
|
1017
|
+
* The instance has a password, or the feed has its own, and it is missing or wrong
|
|
1018
|
+
*/
|
|
1019
|
+
401: Error;
|
|
1020
|
+
/**
|
|
1021
|
+
* Only on an instance with a payment provider (`license_required`): the feed has no active license, and a picture, or a new feed password, is for licensed feeds
|
|
1022
|
+
*/
|
|
1023
|
+
402: Error;
|
|
1024
|
+
/**
|
|
1025
|
+
* Image uploads are off on this instance (`NOTEFEED_IMAGE_UPLOADS=0`, code `images_off`): an image body, a picture replaced, or a multipart body with pictures. Stored pictures are still served
|
|
1026
|
+
*/
|
|
1027
|
+
403: Error;
|
|
1028
|
+
/**
|
|
1029
|
+
* No such feed
|
|
1030
|
+
*/
|
|
1031
|
+
404: Error;
|
|
1032
|
+
/**
|
|
1033
|
+
* An image over NOTEFEED_MAX_IMAGE_BYTES or 100 megapixels
|
|
1034
|
+
*/
|
|
1035
|
+
413: Error;
|
|
1036
|
+
/**
|
|
1037
|
+
* Not an image, or the body is not what it declares
|
|
1038
|
+
*/
|
|
1039
|
+
415: Error;
|
|
1040
|
+
/**
|
|
1041
|
+
* Too many posts, or wrong passwords, from this client
|
|
1042
|
+
*/
|
|
1043
|
+
429: Error;
|
|
1044
|
+
/**
|
|
1045
|
+
* An image the operator removed, which may not be posted again in any feed (`blocked`)
|
|
1046
|
+
*/
|
|
1047
|
+
451: Error;
|
|
1048
|
+
/**
|
|
1049
|
+
* `unavailable`: the key service is unreachable, the instance is down for maintenance. `busy`: too many images are being processed at the moment. Either way, try again after Retry-After
|
|
1050
|
+
*/
|
|
1051
|
+
503: Error;
|
|
1052
|
+
/**
|
|
1053
|
+
* NOTEFEED_MAX_IMAGES_PER_FEED reached
|
|
1054
|
+
*/
|
|
1055
|
+
507: Error;
|
|
1056
|
+
};
|
|
1057
|
+
export type SetFeedImageError = SetFeedImageErrors[keyof SetFeedImageErrors];
|
|
1058
|
+
export type SetFeedImageResponses = {
|
|
1059
|
+
/**
|
|
1060
|
+
* The feed, with its new title image
|
|
1061
|
+
*/
|
|
1062
|
+
200: Feed;
|
|
1063
|
+
};
|
|
1064
|
+
export type SetFeedImageResponse = SetFeedImageResponses[keyof SetFeedImageResponses];
|
|
871
1065
|
export type RemoveFeedPasswordData = {
|
|
872
1066
|
body?: never;
|
|
873
1067
|
headers?: {
|
|
@@ -966,6 +1160,51 @@ export type ChangeFeedPasswordResponses = {
|
|
|
966
1160
|
204: void;
|
|
967
1161
|
};
|
|
968
1162
|
export type ChangeFeedPasswordResponse = ChangeFeedPasswordResponses[keyof ChangeFeedPasswordResponses];
|
|
1163
|
+
export type RecoverFeedPasswordData = {
|
|
1164
|
+
body: RecoveryJson;
|
|
1165
|
+
path: {
|
|
1166
|
+
/**
|
|
1167
|
+
* The feed's name. It is the write key: anyone who knows it can post.
|
|
1168
|
+
*/
|
|
1169
|
+
feed: string;
|
|
1170
|
+
};
|
|
1171
|
+
query?: never;
|
|
1172
|
+
url: '/api/v1/feeds/{feed}/password/recover';
|
|
1173
|
+
};
|
|
1174
|
+
export type RecoverFeedPasswordErrors = {
|
|
1175
|
+
/**
|
|
1176
|
+
* Invalid or reserved feed name, bad JSON, or a new password that is not 1 to 256 printable ASCII characters, with no space at the start or end
|
|
1177
|
+
*/
|
|
1178
|
+
400: Error;
|
|
1179
|
+
/**
|
|
1180
|
+
* The key is not this feed's license, or the feed has no password
|
|
1181
|
+
*/
|
|
1182
|
+
401: Error;
|
|
1183
|
+
/**
|
|
1184
|
+
* The key's license has lapsed, and a new password needs an active one (`license_required`)
|
|
1185
|
+
*/
|
|
1186
|
+
402: Error;
|
|
1187
|
+
/**
|
|
1188
|
+
* Licenses are not sold on this instance, or the feed was deleted meanwhile
|
|
1189
|
+
*/
|
|
1190
|
+
404: Error;
|
|
1191
|
+
/**
|
|
1192
|
+
* Too many wrong passwords or keys from this client
|
|
1193
|
+
*/
|
|
1194
|
+
429: Error;
|
|
1195
|
+
/**
|
|
1196
|
+
* The key service is unreachable: the instance is down for maintenance; try again after Retry-After
|
|
1197
|
+
*/
|
|
1198
|
+
503: Error;
|
|
1199
|
+
};
|
|
1200
|
+
export type RecoverFeedPasswordError = RecoverFeedPasswordErrors[keyof RecoverFeedPasswordErrors];
|
|
1201
|
+
export type RecoverFeedPasswordResponses = {
|
|
1202
|
+
/**
|
|
1203
|
+
* Set or removed; the old password and unlock cookies stop working
|
|
1204
|
+
*/
|
|
1205
|
+
204: void;
|
|
1206
|
+
};
|
|
1207
|
+
export type RecoverFeedPasswordResponse = RecoverFeedPasswordResponses[keyof RecoverFeedPasswordResponses];
|
|
969
1208
|
export type DeleteFeedLicenseData = {
|
|
970
1209
|
body?: never;
|
|
971
1210
|
headers?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notefeed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
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",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^20",
|
|
48
|
-
"typescript": "^
|
|
48
|
+
"typescript": "^7.0",
|
|
49
49
|
"vitest": "^4.1"
|
|
50
50
|
}
|
|
51
51
|
}
|