instapaper-ts 1.0.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.
@@ -0,0 +1,118 @@
1
+ type User = {
2
+ type: "user";
3
+ user_id: number;
4
+ username: string;
5
+ };
6
+ type Bookmark = {
7
+ type: "bookmark";
8
+ hash: string;
9
+ description: string;
10
+ tags: Array<Tag>;
11
+ bookmark_id: number;
12
+ private_source: string;
13
+ title: string;
14
+ url: string;
15
+ progress_timestamp: number;
16
+ time: number;
17
+ progress: number;
18
+ starred: "0" | "1";
19
+ };
20
+ type Folder = {
21
+ type: "folder";
22
+ position: number;
23
+ folder_id: number;
24
+ title: string;
25
+ display_title: string;
26
+ slug: string;
27
+ sync_to_mobile: 0 | 1;
28
+ public: false | 1;
29
+ };
30
+ type Tag = {
31
+ id: number;
32
+ name: string;
33
+ };
34
+ type Highlight = {
35
+ type: "highlight";
36
+ highlight_id: number;
37
+ text: string;
38
+ note: string | null;
39
+ bookmark_id: Bookmark["bookmark_id"];
40
+ time: number;
41
+ position: number;
42
+ };
43
+ type Error = {
44
+ type: "error";
45
+ error_code: number;
46
+ message: string;
47
+ };
48
+ type Meta = {
49
+ type: "meta";
50
+ };
51
+ type ListParams = Partial<{
52
+ limit: number;
53
+ folder_id: "unread" | "starred" | "archive" | (string & {});
54
+ have: string;
55
+ highlights: string;
56
+ }>;
57
+ type UpdateReadProgressParams = {
58
+ bookmark_id: string;
59
+ progress: number;
60
+ progress_timestamp: number;
61
+ };
62
+ type AddBookmarkParams = {
63
+ url: string;
64
+ title?: string;
65
+ description?: string;
66
+ folder_id?: number;
67
+ resolve_final_url?: 0 | 1;
68
+ archived?: 0 | 1;
69
+ tags?: Array<{
70
+ name: string;
71
+ }>;
72
+ is_private_from_source?: string;
73
+ content?: string;
74
+ };
75
+ type AddHighlightParams = {
76
+ bookmark_id: string;
77
+ text: string;
78
+ position?: number;
79
+ };
80
+
81
+ declare class Instapaper {
82
+ private baseUrl;
83
+ private authUrl;
84
+ private oauth;
85
+ private username?;
86
+ private password?;
87
+ private token?;
88
+ constructor(consumerKey: string, consumerSecret: string);
89
+ setCredentials: (username: string, password: string) => void;
90
+ private makeRequest;
91
+ private getAccessToken;
92
+ private request;
93
+ bookmarks: {
94
+ list: (params?: ListParams) => Promise<(Bookmark | Folder | User | Error | Meta)[]>;
95
+ updateReadProgress: (params: UpdateReadProgressParams) => Promise<[Bookmark]>;
96
+ add: (params: AddBookmarkParams) => Promise<[Bookmark]>;
97
+ delete: (bookmark_id: Bookmark["bookmark_id"]) => Promise<never[]>;
98
+ star: (bookmark_id: Bookmark["bookmark_id"]) => Promise<[Bookmark]>;
99
+ unstar: (bookmark_id: Bookmark["bookmark_id"]) => Promise<[Bookmark]>;
100
+ archive: (bookmark_id: Bookmark["bookmark_id"]) => Promise<[Bookmark]>;
101
+ unarchive: (bookmark_id: Bookmark["bookmark_id"]) => Promise<[Bookmark]>;
102
+ move: (bookmark_id: Bookmark["bookmark_id"], folder_id: Folder["folder_id"]) => Promise<[Bookmark]>;
103
+ getText: (bookmark_id: Bookmark["bookmark_id"]) => Promise<string>;
104
+ };
105
+ folders: {
106
+ list: () => Promise<Folder[]>;
107
+ add: (title: string) => Promise<[Folder]>;
108
+ delete: (folder_id: Folder["folder_id"]) => Promise<never[]>;
109
+ setOrder: (order: string) => Promise<Folder[]>;
110
+ };
111
+ highlights: {
112
+ list: (bookmark_id: Bookmark["bookmark_id"]) => Promise<Highlight[]>;
113
+ add: (params: AddHighlightParams) => Promise<Highlight>;
114
+ delete: (highlight_id: string) => Promise<never[]>;
115
+ };
116
+ }
117
+
118
+ export { Instapaper };
package/dist/index.js ADDED
@@ -0,0 +1,132 @@
1
+ // src/index.ts
2
+ import assert from "node:assert";
3
+ import crypto from "node:crypto";
4
+ import OAuth from "oauth-1.0a";
5
+ var Instapaper = class {
6
+ baseUrl = "https://www.instapaper.com/api";
7
+ authUrl = this.baseUrl + "/1/oauth/access_token";
8
+ oauth;
9
+ username;
10
+ password;
11
+ token;
12
+ constructor(consumerKey, consumerSecret) {
13
+ this.oauth = new OAuth({
14
+ consumer: {
15
+ key: consumerKey,
16
+ secret: consumerSecret
17
+ },
18
+ signature_method: "HMAC-SHA1",
19
+ hash_function: (base_string, key) => crypto.createHmac("sha1", key).update(base_string).digest("base64")
20
+ });
21
+ }
22
+ setCredentials = (username, password) => {
23
+ this.username = username;
24
+ this.password = password;
25
+ };
26
+ makeRequest = async (url, method = "POST", params = {}, token) => {
27
+ const form = new URLSearchParams();
28
+ for (const [key, val] of Object.entries(params)) {
29
+ form.append(key, String(val));
30
+ }
31
+ const headers = this.oauth.toHeader(
32
+ this.oauth.authorize(
33
+ {
34
+ url,
35
+ method,
36
+ data: params
37
+ },
38
+ token
39
+ )
40
+ );
41
+ const response = await fetch(url, {
42
+ method,
43
+ headers: new Headers({ ...headers }),
44
+ body: form
45
+ });
46
+ if (!response.ok) {
47
+ const errorText = await response.text();
48
+ throw new Error(`API error: ${response.status} ${errorText}`);
49
+ }
50
+ const contentType = response.headers.get("content-type") || "";
51
+ if (contentType.includes("application/json")) {
52
+ return response.json();
53
+ } else {
54
+ return response.text();
55
+ }
56
+ };
57
+ getAccessToken = async () => {
58
+ assert(
59
+ this.username && this.password,
60
+ "Please set username and password with setCredentials()."
61
+ );
62
+ const params = {
63
+ x_auth_username: this.username,
64
+ x_auth_password: this.password,
65
+ x_auth_mode: "client_auth"
66
+ };
67
+ const responseText = await this.makeRequest(
68
+ this.authUrl,
69
+ "POST",
70
+ params
71
+ );
72
+ const data = new URLSearchParams(responseText);
73
+ const key = data.get("oauth_token");
74
+ const secret = data.get("oauth_token_secret");
75
+ assert(
76
+ key && secret,
77
+ "There was an error fetching the token. One or both of key and secret is null."
78
+ );
79
+ this.token = { key, secret };
80
+ return this.token;
81
+ };
82
+ request = async (endpoint, params = {}) => {
83
+ if (!this.token) {
84
+ this.token = await this.getAccessToken();
85
+ }
86
+ const url = this.baseUrl + endpoint;
87
+ return this.makeRequest(url, "POST", params, this.token);
88
+ };
89
+ bookmarks = {
90
+ list: (params = {}) => this.request(
91
+ "/1/bookmarks/list",
92
+ params
93
+ ),
94
+ updateReadProgress: (params) => this.request(
95
+ "/1/bookmarks/update_read_progress",
96
+ params
97
+ ),
98
+ add: (params) => this.request("/1/bookmarks/add", params),
99
+ delete: (bookmark_id) => this.request("/1/bookmarks/delete", { bookmark_id }),
100
+ star: (bookmark_id) => this.request("/1/bookmarks/star", { bookmark_id }),
101
+ unstar: (bookmark_id) => this.request("/1/bookmarks/unstar", { bookmark_id }),
102
+ archive: (bookmark_id) => this.request("/1/bookmarks/archive", { bookmark_id }),
103
+ unarchive: (bookmark_id) => this.request("/1/bookmarks/unarchive", { bookmark_id }),
104
+ move: (bookmark_id, folder_id) => this.request("/1/bookmarks/move", {
105
+ bookmark_id,
106
+ folder_id
107
+ }),
108
+ getText: (bookmark_id) => this.request("/1/bookmarks/get_text", { bookmark_id })
109
+ };
110
+ folders = {
111
+ list: () => this.request("/1/folders/list"),
112
+ add: (title) => this.request("/1/folders/add", { title }),
113
+ delete: (folder_id) => this.request("/1/folders/delete", { folder_id }),
114
+ setOrder: (order) => this.request("/1/folders/set_order", { order })
115
+ };
116
+ highlights = {
117
+ list: (bookmark_id) => this.request(
118
+ `/1.1/bookmarks/${bookmark_id}/highlights`
119
+ ),
120
+ add: (params) => this.request(
121
+ `/1.1/bookmarks/${params.bookmark_id}/highlight`,
122
+ {
123
+ text: params.text,
124
+ position: params.position
125
+ }
126
+ ),
127
+ delete: (highlight_id) => this.request(`/1.1/highlights/${highlight_id}/delete`)
128
+ };
129
+ };
130
+ export {
131
+ Instapaper
132
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "instapaper-ts",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A type-safe API client for Instapaper.",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "/dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup",
13
+ "dev": "tsup --watch"
14
+ },
15
+ "keywords": [
16
+ "instapaper",
17
+ "read",
18
+ "later",
19
+ "typescript",
20
+ "library"
21
+ ],
22
+ "author": "Ben Silverman (bensilverman.co.uk)",
23
+ "homepage": "https://github.com/benslv/instapaper-ts",
24
+ "bugs": {
25
+ "url": "https://github.com/benslv/instapaper-ts/issues"
26
+ },
27
+ "license": "MIT",
28
+ "packageManager": "pnpm@10.4.1",
29
+ "dependencies": {
30
+ "oauth-1.0a": "^2.2.6"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.13.5",
34
+ "tsup": "^8.4.0",
35
+ "typescript": "^5.8.2"
36
+ }
37
+ }