Skip to content

Commit 768aafd

Browse files
authored
[add] Markdown download API of Lark documents (#12)
1 parent ebd3141 commit 768aafd

File tree

8 files changed

+696
-603
lines changed

8 files changed

+696
-603
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414

1515
- uses: pnpm/action-setup@v4
1616
with:
17-
version: 9
17+
version: 10
1818
- uses: actions/setup-node@v4
1919
with:
20-
node-version: 20
20+
node-version: 22
2121
registry-url: https://registry.npmjs.org
2222
cache: pnpm
2323
- name: Install Dependencies

package.json

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mobx-lark",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"license": "LGPL-3.0",
55
"author": "shiy2008@gmail.com",
66
"description": "Unofficial TypeScript SDK for FeiShu/Lark API, which is based on MobX-RESTful.",
@@ -25,27 +25,32 @@
2525
"url": "https://github.com/idea2app/MobX-Lark/issues"
2626
},
2727
"dependencies": {
28-
"@swc/helpers": "^0.5.15",
29-
"koajax": "^3.1.1",
28+
"@swc/helpers": "^0.5.17",
29+
"koajax": "^3.1.2",
3030
"mobx": "^6.13.7",
3131
"mobx-restful": "^2.1.0",
3232
"regenerator-runtime": "^0.14.1",
3333
"web-utility": "^4.4.3"
3434
},
3535
"devDependencies": {
36-
"@parcel/config-default": "~2.14.0",
37-
"@parcel/transformer-typescript-tsc": "~2.14.0",
38-
"@types/node": "^22.13.10",
39-
"dotenv": "^16.4.7",
36+
"@parcel/config-default": "~2.14.4",
37+
"@parcel/transformer-typescript-tsc": "~2.14.4",
38+
"@types/node": "^22.14.1",
39+
"dotenv": "^16.5.0",
4040
"husky": "^9.1.7",
41-
"lint-staged": "^15.5.0",
41+
"lint-staged": "^15.5.1",
4242
"mobx": "^6.13.7",
43-
"parcel": "~2.14.0",
43+
"parcel": "~2.14.4",
4444
"prettier": "^3.5.3",
4545
"ts-node": "^10.9.2",
46-
"typedoc": "^0.28.0",
46+
"typedoc": "^0.28.2",
4747
"typedoc-plugin-mdn-links": "^5.0.1",
48-
"typescript": "~5.8.2"
48+
"typescript": "~5.8.3"
49+
},
50+
"pnpm": {
51+
"onlyBuiltDependencies": [
52+
"@swc/core"
53+
]
4954
},
5055
"prettier": {
5156
"singleQuote": true,

pnpm-lock.yaml

Lines changed: 597 additions & 581 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Lark.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Context, HTTPClient, makeFormData } from 'koajax';
22
import { buildURLData, cache, Second } from 'web-utility';
33

4+
import { LarkWikiNode } from './module';
45
import {
56
isLarkError,
67
JSTicket,
@@ -165,11 +166,17 @@ export class LarkApp implements LarkAppOption {
165166
async downloadFile(id: string) {
166167
await this.getAccessToken();
167168

168-
const { body } = await this.client.request<ArrayBuffer>({
169-
path: `drive/v1/medias/${id}/download`,
170-
responseType: 'arraybuffer'
171-
});
172-
return body!;
169+
const { headers, body } = await this.client.get<Blob>(
170+
`drive/v1/medias/${id}/download`,
171+
{},
172+
{ responseType: 'blob' }
173+
);
174+
const { 'Content-Disposition': CD, 'Content-Type': CT } = headers;
175+
176+
const [type] = (CT as string)?.split(';') || [],
177+
[, fileName] = (CD as string)?.match(/filename="?(.*?)"?$/) || [];
178+
179+
return new File([body!], fileName, { type });
173180
}
174181

175182
/**
@@ -195,4 +202,41 @@ export class LarkApp implements LarkAppOption {
195202

196203
return body!.data!.file_token;
197204
}
205+
206+
/**
207+
* @see {@link https://open.feishu.cn/document/server-docs/docs/wiki-v2/space-node/get_node}
208+
*/
209+
async wiki2docx(id: string) {
210+
await this.getAccessToken();
211+
212+
const { body } = await this.client.get<
213+
LarkData<{ node: LarkWikiNode }>
214+
>(`wiki/v2/spaces/get_node?token=${id}`);
215+
216+
const { obj_type, obj_token } = body!.data!.node;
217+
218+
return obj_type === 'docx' ? obj_token : '';
219+
}
220+
221+
static documentPathPattern = /(wiki|docx)\/(\w+)/;
222+
223+
/**
224+
* @see {@link https://open.feishu.cn/document/ukTMukTMukTM/uUDN04SN0QjL1QDN/docs-v1/content/get}
225+
*/
226+
async downloadMarkdown(URI: string) {
227+
await this.getAccessToken();
228+
229+
const [, type, id] = URI.match(LarkApp.documentPathPattern) || [];
230+
231+
const doc_token = type === 'wiki' ? await this.wiki2docx(id) : id;
232+
233+
const { body } = await this.client.get<LarkData<{ content: string }>>(
234+
`docs/v1/content?${new URLSearchParams({
235+
doc_type: 'docx',
236+
doc_token,
237+
content_type: 'markdown'
238+
})}`
239+
);
240+
return body!.data!.content;
241+
}
198242
}

src/module/BITable/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,19 @@ export function BiDataTable<
6161
this.baseURI = `bitable/v1/apps/${appId}/tables/${tableId}/records`;
6262
}
6363

64-
normalize({ fields, ...meta }: TableRecord<T>): T {
64+
extractFields({ fields, ...meta }: TableRecord<T>): T {
6565
return { ...meta, ...fields };
6666
}
6767

68+
/**
69+
* @deprecated
70+
*/
71+
normalize = this.extractFields;
72+
73+
wrapFields(fields: F) {
74+
return fields as unknown as T;
75+
}
76+
6877
/**
6978
* @see {@link https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/get}
7079
*/
@@ -81,7 +90,9 @@ export function BiDataTable<
8190
* @see {@link https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/update}
8291
*/
8392
@toggle('uploading')
84-
async updateOne(fields: F, id?: string) {
93+
async updateOne(data: F, id?: string) {
94+
const fields = this.wrapFields(data);
95+
8596
const { body } = await (id
8697
? this.client.put<TableRecordData<T>>(`${this.baseURI}/${id}`, {
8798
fields

src/module/Wiki/type.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export interface LarkWikiNode
2+
extends Record<
3+
| 'title'
4+
| 'creator'
5+
| 'owner'
6+
| `${'' | 'origin_'}space_id`
7+
| `node_create_time`
8+
| `${'' | 'parent_' | 'origin_'}node_token`
9+
| `obj_token`
10+
| `obj_${'create' | 'edit'}_time`,
11+
string
12+
> {
13+
node_type: 'origin' | 'shortcut';
14+
obj_type: `doc${'' | 'x'}` | 'sheet' | 'mindnote' | 'bitable' | 'file';
15+
has_child: boolean;
16+
}

src/module/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './InstantMessenger';
33
export * from './Task';
44
export * from './SpreadSheet';
55
export * from './BITable';
6+
export * from './Wiki/type';

test/index.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ describe('MobX Lark SDK', async () => {
121121
});
122122

123123
await it('should download a file', async expect => {
124-
const file = await app.downloadFile(MEDIA_ID!);
124+
const { size } = await app.downloadFile(MEDIA_ID!);
125125

126-
expect(file.byteLength > 0);
126+
expect(size > 0);
127127
});
128128
}).finally(() => process.exit());

0 commit comments

Comments
 (0)