memory-sdk 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -0
- package/dist/index.d.mts +74 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +111 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +27 -0
- package/src/client.ts +143 -0
- package/src/index.ts +2 -0
- package/src/types.ts +46 -0
- package/tsconfig.json +19 -0
- package/tsup.config.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# memory-sdk
|
|
2
|
+
|
|
3
|
+
AgentLink Memory API 客户端:使用 API Key 对 `/api/memory/v1/memories` 进行 CRUD 与列表/搜索,适用于 Node 与浏览器。
|
|
4
|
+
|
|
5
|
+
## 获取 API Key
|
|
6
|
+
|
|
7
|
+
在 [Memory 设置页](https://www.mixlab.top/memory/settings) 的「API Key」区域创建 Key,格式为 `al_` 开头。请求时需在请求头中携带:`Authorization: Bearer <key>` 或 `X-Api-Key: <key>`,本 SDK 使用 Bearer 方式。
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install memory-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 使用
|
|
16
|
+
|
|
17
|
+
### 连接官方站(默认)
|
|
18
|
+
|
|
19
|
+
不传 `baseUrl` 时,默认请求 `https://www.mixlab.top/api`。
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { MemoryClient } from 'memory-sdk';
|
|
23
|
+
|
|
24
|
+
const client = new MemoryClient({ apiKey: 'al_xxx' });
|
|
25
|
+
|
|
26
|
+
// 列表
|
|
27
|
+
const list = await client.list();
|
|
28
|
+
const filtered = await client.list({ category: '笔记', limit: 20, offset: 0 });
|
|
29
|
+
|
|
30
|
+
// 搜索
|
|
31
|
+
const results = await client.search('关键词', 50);
|
|
32
|
+
|
|
33
|
+
// 单条
|
|
34
|
+
const one = await client.get('memory-id'); // 404 时为 null
|
|
35
|
+
|
|
36
|
+
// 创建
|
|
37
|
+
const created = await client.create({
|
|
38
|
+
source: 'https://example.com',
|
|
39
|
+
category: '阅读',
|
|
40
|
+
content: '内容摘要',
|
|
41
|
+
tags: ['tag1'],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 更新
|
|
45
|
+
const updated = await client.update(created.id, { content: '更新后的内容' });
|
|
46
|
+
|
|
47
|
+
// 删除
|
|
48
|
+
await client.delete(created.id);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 自建或同源
|
|
52
|
+
|
|
53
|
+
传入 `baseUrl` 即可:
|
|
54
|
+
|
|
55
|
+
- 自建服务:`baseUrl: 'https://your-domain.com/api'`
|
|
56
|
+
- 浏览器同源:`baseUrl: window.location.origin + '/api'`
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const client = new MemoryClient({
|
|
60
|
+
apiKey: 'al_xxx',
|
|
61
|
+
baseUrl: 'https://your-domain.com/api',
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 类型
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import type { Memory, CreatePayload, UpdatePayload, ListParams } from 'memory-sdk';
|
|
69
|
+
import { DEFAULT_BASE_URL } from 'memory-sdk';
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API
|
|
73
|
+
|
|
74
|
+
- `list(params?: ListParams): Promise<Memory[]>` — 列表,支持 `category`、`source`、`tag`、`limit`、`offset`
|
|
75
|
+
- `search(q: string, limit?: number): Promise<Memory[]>` — 关键词搜索
|
|
76
|
+
- `get(id: string): Promise<Memory | null>` — 按 id 获取,404 返回 `null`
|
|
77
|
+
- `create(payload: CreatePayload): Promise<Memory>` — 创建(`source`、`category`、`content` 必填)
|
|
78
|
+
- `update(id: string, payload: UpdatePayload): Promise<Memory>` — 更新
|
|
79
|
+
- `delete(id: string): Promise<void>` — 删除
|
|
80
|
+
|
|
81
|
+
非 2xx 响应会解析 `{ error?: string }` 并抛出 `Error`。
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory 数据类型定义(与后端 API 返回对齐)
|
|
3
|
+
*/
|
|
4
|
+
interface Memory {
|
|
5
|
+
id: string;
|
|
6
|
+
source: string;
|
|
7
|
+
category: string;
|
|
8
|
+
content: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
images?: string[];
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
metadata?: unknown;
|
|
14
|
+
rawData?: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** 创建 Memory 的请求体:source、category、content 必填 */
|
|
17
|
+
interface CreatePayload {
|
|
18
|
+
source: string;
|
|
19
|
+
category: string;
|
|
20
|
+
content: string;
|
|
21
|
+
tags?: string[];
|
|
22
|
+
images?: string[];
|
|
23
|
+
metadata?: unknown;
|
|
24
|
+
rawData?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** 更新 Memory 的请求体:全部可选 */
|
|
27
|
+
interface UpdatePayload {
|
|
28
|
+
source?: string;
|
|
29
|
+
category?: string;
|
|
30
|
+
content?: string;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
images?: string[];
|
|
33
|
+
metadata?: unknown;
|
|
34
|
+
rawData?: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** 列表/筛选参数(对应 GET 的 searchParams) */
|
|
37
|
+
interface ListParams {
|
|
38
|
+
category?: string;
|
|
39
|
+
source?: string;
|
|
40
|
+
tag?: string;
|
|
41
|
+
limit?: number;
|
|
42
|
+
offset?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 默认 API 基础地址(含 /api 前缀) */
|
|
46
|
+
declare const DEFAULT_BASE_URL = "https://www.mixlab.top/api";
|
|
47
|
+
interface MemoryClientOptions {
|
|
48
|
+
apiKey: string;
|
|
49
|
+
baseUrl?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Memory API 客户端:使用 API Key 调用 /api/memory/v1/memories 的 CRUD 与列表/搜索。
|
|
53
|
+
*/
|
|
54
|
+
declare class MemoryClient {
|
|
55
|
+
private readonly apiKey;
|
|
56
|
+
private readonly baseUrl;
|
|
57
|
+
constructor(options: MemoryClientOptions);
|
|
58
|
+
private url;
|
|
59
|
+
private headers;
|
|
60
|
+
/** 列表,支持 category / source / tag / limit / offset */
|
|
61
|
+
list(params?: ListParams): Promise<Memory[]>;
|
|
62
|
+
/** 关键词搜索 */
|
|
63
|
+
search(q: string, limit?: number): Promise<Memory[]>;
|
|
64
|
+
/** 按 id 获取单条,404 返回 null */
|
|
65
|
+
get(id: string): Promise<Memory | null>;
|
|
66
|
+
/** 创建 */
|
|
67
|
+
create(payload: CreatePayload): Promise<Memory>;
|
|
68
|
+
/** 更新 */
|
|
69
|
+
update(id: string, payload: UpdatePayload): Promise<Memory>;
|
|
70
|
+
/** 删除 */
|
|
71
|
+
delete(id: string): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type CreatePayload, DEFAULT_BASE_URL, type ListParams, type Memory, MemoryClient, type MemoryClientOptions, type UpdatePayload };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory 数据类型定义(与后端 API 返回对齐)
|
|
3
|
+
*/
|
|
4
|
+
interface Memory {
|
|
5
|
+
id: string;
|
|
6
|
+
source: string;
|
|
7
|
+
category: string;
|
|
8
|
+
content: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
images?: string[];
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
metadata?: unknown;
|
|
14
|
+
rawData?: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** 创建 Memory 的请求体:source、category、content 必填 */
|
|
17
|
+
interface CreatePayload {
|
|
18
|
+
source: string;
|
|
19
|
+
category: string;
|
|
20
|
+
content: string;
|
|
21
|
+
tags?: string[];
|
|
22
|
+
images?: string[];
|
|
23
|
+
metadata?: unknown;
|
|
24
|
+
rawData?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** 更新 Memory 的请求体:全部可选 */
|
|
27
|
+
interface UpdatePayload {
|
|
28
|
+
source?: string;
|
|
29
|
+
category?: string;
|
|
30
|
+
content?: string;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
images?: string[];
|
|
33
|
+
metadata?: unknown;
|
|
34
|
+
rawData?: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** 列表/筛选参数(对应 GET 的 searchParams) */
|
|
37
|
+
interface ListParams {
|
|
38
|
+
category?: string;
|
|
39
|
+
source?: string;
|
|
40
|
+
tag?: string;
|
|
41
|
+
limit?: number;
|
|
42
|
+
offset?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 默认 API 基础地址(含 /api 前缀) */
|
|
46
|
+
declare const DEFAULT_BASE_URL = "https://www.mixlab.top/api";
|
|
47
|
+
interface MemoryClientOptions {
|
|
48
|
+
apiKey: string;
|
|
49
|
+
baseUrl?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Memory API 客户端:使用 API Key 调用 /api/memory/v1/memories 的 CRUD 与列表/搜索。
|
|
53
|
+
*/
|
|
54
|
+
declare class MemoryClient {
|
|
55
|
+
private readonly apiKey;
|
|
56
|
+
private readonly baseUrl;
|
|
57
|
+
constructor(options: MemoryClientOptions);
|
|
58
|
+
private url;
|
|
59
|
+
private headers;
|
|
60
|
+
/** 列表,支持 category / source / tag / limit / offset */
|
|
61
|
+
list(params?: ListParams): Promise<Memory[]>;
|
|
62
|
+
/** 关键词搜索 */
|
|
63
|
+
search(q: string, limit?: number): Promise<Memory[]>;
|
|
64
|
+
/** 按 id 获取单条,404 返回 null */
|
|
65
|
+
get(id: string): Promise<Memory | null>;
|
|
66
|
+
/** 创建 */
|
|
67
|
+
create(payload: CreatePayload): Promise<Memory>;
|
|
68
|
+
/** 更新 */
|
|
69
|
+
update(id: string, payload: UpdatePayload): Promise<Memory>;
|
|
70
|
+
/** 删除 */
|
|
71
|
+
delete(id: string): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type CreatePayload, DEFAULT_BASE_URL, type ListParams, type Memory, MemoryClient, type MemoryClientOptions, type UpdatePayload };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
24
|
+
MemoryClient: () => MemoryClient
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/client.ts
|
|
29
|
+
var DEFAULT_BASE_URL = "https://www.mixlab.top/api";
|
|
30
|
+
var MEMORIES_PATH = "/memory/v1/memories";
|
|
31
|
+
function toMemory(record) {
|
|
32
|
+
const tags = Array.isArray(record.tags) ? record.tags : [];
|
|
33
|
+
return {
|
|
34
|
+
id: record.id,
|
|
35
|
+
source: record.source,
|
|
36
|
+
category: record.category,
|
|
37
|
+
content: record.content,
|
|
38
|
+
tags,
|
|
39
|
+
images: record.images?.length ? record.images : void 0,
|
|
40
|
+
createdAt: record.createdAt,
|
|
41
|
+
updatedAt: record.updatedAt,
|
|
42
|
+
metadata: record.metadata,
|
|
43
|
+
rawData: record.rawData
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function handleResponse(res, parse) {
|
|
47
|
+
const data = await res.json().catch(() => ({}));
|
|
48
|
+
if (!res.ok) {
|
|
49
|
+
const err = data && typeof data === "object" && "error" in data ? String(data.error) : `HTTP ${res.status}`;
|
|
50
|
+
throw new Error(err);
|
|
51
|
+
}
|
|
52
|
+
return parse(data);
|
|
53
|
+
}
|
|
54
|
+
var MemoryClient = class {
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.apiKey = options.apiKey;
|
|
57
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
58
|
+
}
|
|
59
|
+
url(path, searchParams) {
|
|
60
|
+
const u = `${this.baseUrl}${path}`;
|
|
61
|
+
if (!searchParams || Object.keys(searchParams).length === 0) return u;
|
|
62
|
+
const sp = new URLSearchParams(searchParams);
|
|
63
|
+
return `${u}?${sp.toString()}`;
|
|
64
|
+
}
|
|
65
|
+
headers(init) {
|
|
66
|
+
return {
|
|
67
|
+
"Content-Type": "application/json",
|
|
68
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
69
|
+
...init
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** 列表,支持 category / source / tag / limit / offset */
|
|
73
|
+
async list(params) {
|
|
74
|
+
const searchParams = {};
|
|
75
|
+
if (params?.category) searchParams.category = params.category;
|
|
76
|
+
if (params?.source) searchParams.source = params.source;
|
|
77
|
+
if (params?.tag) searchParams.tag = params.tag;
|
|
78
|
+
if (params?.limit != null) searchParams.limit = String(params.limit);
|
|
79
|
+
if (params?.offset != null) searchParams.offset = String(params.offset);
|
|
80
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
81
|
+
const list = await handleResponse(res, (data) => Array.isArray(data) ? data : []);
|
|
82
|
+
return list.map(toMemory);
|
|
83
|
+
}
|
|
84
|
+
/** 关键词搜索 */
|
|
85
|
+
async search(q, limit) {
|
|
86
|
+
const searchParams = { q };
|
|
87
|
+
if (limit != null) searchParams.limit = String(limit);
|
|
88
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
89
|
+
const list = await handleResponse(res, (data) => Array.isArray(data) ? data : []);
|
|
90
|
+
return list.map(toMemory);
|
|
91
|
+
}
|
|
92
|
+
/** 按 id 获取单条,404 返回 null */
|
|
93
|
+
async get(id) {
|
|
94
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
95
|
+
headers: this.headers()
|
|
96
|
+
});
|
|
97
|
+
if (res.status === 404) return null;
|
|
98
|
+
const record = await handleResponse(res, (x) => x);
|
|
99
|
+
return toMemory(record);
|
|
100
|
+
}
|
|
101
|
+
/** 创建 */
|
|
102
|
+
async create(payload) {
|
|
103
|
+
const res = await fetch(this.url(MEMORIES_PATH), {
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers: this.headers(),
|
|
106
|
+
body: JSON.stringify(payload)
|
|
107
|
+
});
|
|
108
|
+
const record = await handleResponse(res, (x) => x);
|
|
109
|
+
return toMemory(record);
|
|
110
|
+
}
|
|
111
|
+
/** 更新 */
|
|
112
|
+
async update(id, payload) {
|
|
113
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
114
|
+
method: "PATCH",
|
|
115
|
+
headers: this.headers(),
|
|
116
|
+
body: JSON.stringify(payload)
|
|
117
|
+
});
|
|
118
|
+
const record = await handleResponse(res, (x) => x);
|
|
119
|
+
return toMemory(record);
|
|
120
|
+
}
|
|
121
|
+
/** 删除 */
|
|
122
|
+
async delete(id) {
|
|
123
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
124
|
+
method: "DELETE",
|
|
125
|
+
headers: this.headers()
|
|
126
|
+
});
|
|
127
|
+
if (!res.ok) {
|
|
128
|
+
const data = await res.json().catch(() => ({}));
|
|
129
|
+
const err = data && typeof data === "object" && "error" in data ? String(data.error) : `HTTP ${res.status}`;
|
|
130
|
+
throw new Error(err);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
135
|
+
0 && (module.exports = {
|
|
136
|
+
DEFAULT_BASE_URL,
|
|
137
|
+
MemoryClient
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["export { MemoryClient, DEFAULT_BASE_URL, type MemoryClientOptions } from './client';\nexport type { Memory, CreatePayload, UpdatePayload, ListParams } from './types';\n","import type { CreatePayload, ListParams, Memory, UpdatePayload } from './types';\n\n/** 默认 API 基础地址(含 /api 前缀) */\nexport const DEFAULT_BASE_URL = 'https://www.mixlab.top/api';\n\nconst MEMORIES_PATH = '/memory/v1/memories';\n\nfunction toMemory(record: {\n id: string;\n source: string;\n category: string;\n content: string;\n tags: string[] | unknown;\n images?: string[];\n createdAt: number;\n updatedAt: number;\n metadata?: unknown;\n rawData?: unknown;\n}): Memory {\n const tags = Array.isArray(record.tags) ? record.tags : [];\n return {\n id: record.id,\n source: record.source,\n category: record.category,\n content: record.content,\n tags,\n images: record.images?.length ? record.images : undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n metadata: record.metadata,\n rawData: record.rawData,\n };\n}\n\nasync function handleResponse<T>(res: Response, parse: (data: unknown) => T): Promise<T> {\n const data = await res.json().catch(() => ({}));\n if (!res.ok) {\n const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;\n throw new Error(err);\n }\n return parse(data);\n}\n\nexport interface MemoryClientOptions {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Memory API 客户端:使用 API Key 调用 /api/memory/v1/memories 的 CRUD 与列表/搜索。\n */\nexport class MemoryClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(options: MemoryClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n }\n\n private url(path: string, searchParams?: Record<string, string>): string {\n const u = `${this.baseUrl}${path}`;\n if (!searchParams || Object.keys(searchParams).length === 0) return u;\n const sp = new URLSearchParams(searchParams);\n return `${u}?${sp.toString()}`;\n }\n\n private headers(init?: Record<string, string>): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...init,\n };\n }\n\n /** 列表,支持 category / source / tag / limit / offset */\n async list(params?: ListParams): Promise<Memory[]> {\n const searchParams: Record<string, string> = {};\n if (params?.category) searchParams.category = params.category;\n if (params?.source) searchParams.source = params.source;\n if (params?.tag) searchParams.tag = params.tag;\n if (params?.limit != null) searchParams.limit = String(params.limit);\n if (params?.offset != null) searchParams.offset = String(params.offset);\n\n const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });\n const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));\n return list.map(toMemory);\n }\n\n /** 关键词搜索 */\n async search(q: string, limit?: number): Promise<Memory[]> {\n const searchParams: Record<string, string> = { q };\n if (limit != null) searchParams.limit = String(limit);\n const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });\n const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));\n return list.map(toMemory);\n }\n\n /** 按 id 获取单条,404 返回 null */\n async get(id: string): Promise<Memory | null> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n headers: this.headers(),\n });\n if (res.status === 404) return null;\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 创建 */\n async create(payload: CreatePayload): Promise<Memory> {\n const res = await fetch(this.url(MEMORIES_PATH), {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(payload),\n });\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 更新 */\n async update(id: string, payload: UpdatePayload): Promise<Memory> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(payload),\n });\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 删除 */\n async delete(id: string): Promise<void> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n method: 'DELETE',\n headers: this.headers(),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;\n throw new Error(err);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://www.mixlab.top/api";
|
|
3
|
+
var MEMORIES_PATH = "/memory/v1/memories";
|
|
4
|
+
function toMemory(record) {
|
|
5
|
+
const tags = Array.isArray(record.tags) ? record.tags : [];
|
|
6
|
+
return {
|
|
7
|
+
id: record.id,
|
|
8
|
+
source: record.source,
|
|
9
|
+
category: record.category,
|
|
10
|
+
content: record.content,
|
|
11
|
+
tags,
|
|
12
|
+
images: record.images?.length ? record.images : void 0,
|
|
13
|
+
createdAt: record.createdAt,
|
|
14
|
+
updatedAt: record.updatedAt,
|
|
15
|
+
metadata: record.metadata,
|
|
16
|
+
rawData: record.rawData
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function handleResponse(res, parse) {
|
|
20
|
+
const data = await res.json().catch(() => ({}));
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const err = data && typeof data === "object" && "error" in data ? String(data.error) : `HTTP ${res.status}`;
|
|
23
|
+
throw new Error(err);
|
|
24
|
+
}
|
|
25
|
+
return parse(data);
|
|
26
|
+
}
|
|
27
|
+
var MemoryClient = class {
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.apiKey = options.apiKey;
|
|
30
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
31
|
+
}
|
|
32
|
+
url(path, searchParams) {
|
|
33
|
+
const u = `${this.baseUrl}${path}`;
|
|
34
|
+
if (!searchParams || Object.keys(searchParams).length === 0) return u;
|
|
35
|
+
const sp = new URLSearchParams(searchParams);
|
|
36
|
+
return `${u}?${sp.toString()}`;
|
|
37
|
+
}
|
|
38
|
+
headers(init) {
|
|
39
|
+
return {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
42
|
+
...init
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** 列表,支持 category / source / tag / limit / offset */
|
|
46
|
+
async list(params) {
|
|
47
|
+
const searchParams = {};
|
|
48
|
+
if (params?.category) searchParams.category = params.category;
|
|
49
|
+
if (params?.source) searchParams.source = params.source;
|
|
50
|
+
if (params?.tag) searchParams.tag = params.tag;
|
|
51
|
+
if (params?.limit != null) searchParams.limit = String(params.limit);
|
|
52
|
+
if (params?.offset != null) searchParams.offset = String(params.offset);
|
|
53
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
54
|
+
const list = await handleResponse(res, (data) => Array.isArray(data) ? data : []);
|
|
55
|
+
return list.map(toMemory);
|
|
56
|
+
}
|
|
57
|
+
/** 关键词搜索 */
|
|
58
|
+
async search(q, limit) {
|
|
59
|
+
const searchParams = { q };
|
|
60
|
+
if (limit != null) searchParams.limit = String(limit);
|
|
61
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
62
|
+
const list = await handleResponse(res, (data) => Array.isArray(data) ? data : []);
|
|
63
|
+
return list.map(toMemory);
|
|
64
|
+
}
|
|
65
|
+
/** 按 id 获取单条,404 返回 null */
|
|
66
|
+
async get(id) {
|
|
67
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
68
|
+
headers: this.headers()
|
|
69
|
+
});
|
|
70
|
+
if (res.status === 404) return null;
|
|
71
|
+
const record = await handleResponse(res, (x) => x);
|
|
72
|
+
return toMemory(record);
|
|
73
|
+
}
|
|
74
|
+
/** 创建 */
|
|
75
|
+
async create(payload) {
|
|
76
|
+
const res = await fetch(this.url(MEMORIES_PATH), {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: this.headers(),
|
|
79
|
+
body: JSON.stringify(payload)
|
|
80
|
+
});
|
|
81
|
+
const record = await handleResponse(res, (x) => x);
|
|
82
|
+
return toMemory(record);
|
|
83
|
+
}
|
|
84
|
+
/** 更新 */
|
|
85
|
+
async update(id, payload) {
|
|
86
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
87
|
+
method: "PATCH",
|
|
88
|
+
headers: this.headers(),
|
|
89
|
+
body: JSON.stringify(payload)
|
|
90
|
+
});
|
|
91
|
+
const record = await handleResponse(res, (x) => x);
|
|
92
|
+
return toMemory(record);
|
|
93
|
+
}
|
|
94
|
+
/** 删除 */
|
|
95
|
+
async delete(id) {
|
|
96
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
97
|
+
method: "DELETE",
|
|
98
|
+
headers: this.headers()
|
|
99
|
+
});
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
const data = await res.json().catch(() => ({}));
|
|
102
|
+
const err = data && typeof data === "object" && "error" in data ? String(data.error) : `HTTP ${res.status}`;
|
|
103
|
+
throw new Error(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
export {
|
|
108
|
+
DEFAULT_BASE_URL,
|
|
109
|
+
MemoryClient
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { CreatePayload, ListParams, Memory, UpdatePayload } from './types';\n\n/** 默认 API 基础地址(含 /api 前缀) */\nexport const DEFAULT_BASE_URL = 'https://www.mixlab.top/api';\n\nconst MEMORIES_PATH = '/memory/v1/memories';\n\nfunction toMemory(record: {\n id: string;\n source: string;\n category: string;\n content: string;\n tags: string[] | unknown;\n images?: string[];\n createdAt: number;\n updatedAt: number;\n metadata?: unknown;\n rawData?: unknown;\n}): Memory {\n const tags = Array.isArray(record.tags) ? record.tags : [];\n return {\n id: record.id,\n source: record.source,\n category: record.category,\n content: record.content,\n tags,\n images: record.images?.length ? record.images : undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n metadata: record.metadata,\n rawData: record.rawData,\n };\n}\n\nasync function handleResponse<T>(res: Response, parse: (data: unknown) => T): Promise<T> {\n const data = await res.json().catch(() => ({}));\n if (!res.ok) {\n const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;\n throw new Error(err);\n }\n return parse(data);\n}\n\nexport interface MemoryClientOptions {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Memory API 客户端:使用 API Key 调用 /api/memory/v1/memories 的 CRUD 与列表/搜索。\n */\nexport class MemoryClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(options: MemoryClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n }\n\n private url(path: string, searchParams?: Record<string, string>): string {\n const u = `${this.baseUrl}${path}`;\n if (!searchParams || Object.keys(searchParams).length === 0) return u;\n const sp = new URLSearchParams(searchParams);\n return `${u}?${sp.toString()}`;\n }\n\n private headers(init?: Record<string, string>): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...init,\n };\n }\n\n /** 列表,支持 category / source / tag / limit / offset */\n async list(params?: ListParams): Promise<Memory[]> {\n const searchParams: Record<string, string> = {};\n if (params?.category) searchParams.category = params.category;\n if (params?.source) searchParams.source = params.source;\n if (params?.tag) searchParams.tag = params.tag;\n if (params?.limit != null) searchParams.limit = String(params.limit);\n if (params?.offset != null) searchParams.offset = String(params.offset);\n\n const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });\n const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));\n return list.map(toMemory);\n }\n\n /** 关键词搜索 */\n async search(q: string, limit?: number): Promise<Memory[]> {\n const searchParams: Record<string, string> = { q };\n if (limit != null) searchParams.limit = String(limit);\n const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });\n const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));\n return list.map(toMemory);\n }\n\n /** 按 id 获取单条,404 返回 null */\n async get(id: string): Promise<Memory | null> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n headers: this.headers(),\n });\n if (res.status === 404) return null;\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 创建 */\n async create(payload: CreatePayload): Promise<Memory> {\n const res = await fetch(this.url(MEMORIES_PATH), {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(payload),\n });\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 更新 */\n async update(id: string, payload: UpdatePayload): Promise<Memory> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(payload),\n });\n const record = await handleResponse(res, (x) => x);\n return toMemory(record as Parameters<typeof toMemory>[0]);\n }\n\n /** 删除 */\n async delete(id: string): Promise<void> {\n const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {\n method: 'DELETE',\n headers: this.headers(),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;\n throw new Error(err);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memory-sdk",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "AgentLink Memory API client - CRUD and search with API Key",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"clean": "rimraf dist"
|
|
18
|
+
},
|
|
19
|
+
"keywords": ["agentlink", "memory", "api", "sdk"],
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^20.0.0",
|
|
23
|
+
"rimraf": "^4.4.0",
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.0.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { CreatePayload, ListParams, Memory, UpdatePayload } from './types';
|
|
2
|
+
|
|
3
|
+
/** 默认 API 基础地址(含 /api 前缀) */
|
|
4
|
+
export const DEFAULT_BASE_URL = 'https://www.mixlab.top/api';
|
|
5
|
+
|
|
6
|
+
const MEMORIES_PATH = '/memory/v1/memories';
|
|
7
|
+
|
|
8
|
+
function toMemory(record: {
|
|
9
|
+
id: string;
|
|
10
|
+
source: string;
|
|
11
|
+
category: string;
|
|
12
|
+
content: string;
|
|
13
|
+
tags: string[] | unknown;
|
|
14
|
+
images?: string[];
|
|
15
|
+
createdAt: number;
|
|
16
|
+
updatedAt: number;
|
|
17
|
+
metadata?: unknown;
|
|
18
|
+
rawData?: unknown;
|
|
19
|
+
}): Memory {
|
|
20
|
+
const tags = Array.isArray(record.tags) ? record.tags : [];
|
|
21
|
+
return {
|
|
22
|
+
id: record.id,
|
|
23
|
+
source: record.source,
|
|
24
|
+
category: record.category,
|
|
25
|
+
content: record.content,
|
|
26
|
+
tags,
|
|
27
|
+
images: record.images?.length ? record.images : undefined,
|
|
28
|
+
createdAt: record.createdAt,
|
|
29
|
+
updatedAt: record.updatedAt,
|
|
30
|
+
metadata: record.metadata,
|
|
31
|
+
rawData: record.rawData,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function handleResponse<T>(res: Response, parse: (data: unknown) => T): Promise<T> {
|
|
36
|
+
const data = await res.json().catch(() => ({}));
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;
|
|
39
|
+
throw new Error(err);
|
|
40
|
+
}
|
|
41
|
+
return parse(data);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MemoryClientOptions {
|
|
45
|
+
apiKey: string;
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Memory API 客户端:使用 API Key 调用 /api/memory/v1/memories 的 CRUD 与列表/搜索。
|
|
51
|
+
*/
|
|
52
|
+
export class MemoryClient {
|
|
53
|
+
private readonly apiKey: string;
|
|
54
|
+
private readonly baseUrl: string;
|
|
55
|
+
|
|
56
|
+
constructor(options: MemoryClientOptions) {
|
|
57
|
+
this.apiKey = options.apiKey;
|
|
58
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private url(path: string, searchParams?: Record<string, string>): string {
|
|
62
|
+
const u = `${this.baseUrl}${path}`;
|
|
63
|
+
if (!searchParams || Object.keys(searchParams).length === 0) return u;
|
|
64
|
+
const sp = new URLSearchParams(searchParams);
|
|
65
|
+
return `${u}?${sp.toString()}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private headers(init?: Record<string, string>): Record<string, string> {
|
|
69
|
+
return {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
72
|
+
...init,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** 列表,支持 category / source / tag / limit / offset */
|
|
77
|
+
async list(params?: ListParams): Promise<Memory[]> {
|
|
78
|
+
const searchParams: Record<string, string> = {};
|
|
79
|
+
if (params?.category) searchParams.category = params.category;
|
|
80
|
+
if (params?.source) searchParams.source = params.source;
|
|
81
|
+
if (params?.tag) searchParams.tag = params.tag;
|
|
82
|
+
if (params?.limit != null) searchParams.limit = String(params.limit);
|
|
83
|
+
if (params?.offset != null) searchParams.offset = String(params.offset);
|
|
84
|
+
|
|
85
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
86
|
+
const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));
|
|
87
|
+
return list.map(toMemory);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** 关键词搜索 */
|
|
91
|
+
async search(q: string, limit?: number): Promise<Memory[]> {
|
|
92
|
+
const searchParams: Record<string, string> = { q };
|
|
93
|
+
if (limit != null) searchParams.limit = String(limit);
|
|
94
|
+
const res = await fetch(this.url(MEMORIES_PATH, searchParams), { headers: this.headers() });
|
|
95
|
+
const list = await handleResponse(res, (data) => (Array.isArray(data) ? data : []));
|
|
96
|
+
return list.map(toMemory);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** 按 id 获取单条,404 返回 null */
|
|
100
|
+
async get(id: string): Promise<Memory | null> {
|
|
101
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
102
|
+
headers: this.headers(),
|
|
103
|
+
});
|
|
104
|
+
if (res.status === 404) return null;
|
|
105
|
+
const record = await handleResponse(res, (x) => x);
|
|
106
|
+
return toMemory(record as Parameters<typeof toMemory>[0]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** 创建 */
|
|
110
|
+
async create(payload: CreatePayload): Promise<Memory> {
|
|
111
|
+
const res = await fetch(this.url(MEMORIES_PATH), {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: this.headers(),
|
|
114
|
+
body: JSON.stringify(payload),
|
|
115
|
+
});
|
|
116
|
+
const record = await handleResponse(res, (x) => x);
|
|
117
|
+
return toMemory(record as Parameters<typeof toMemory>[0]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** 更新 */
|
|
121
|
+
async update(id: string, payload: UpdatePayload): Promise<Memory> {
|
|
122
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
123
|
+
method: 'PATCH',
|
|
124
|
+
headers: this.headers(),
|
|
125
|
+
body: JSON.stringify(payload),
|
|
126
|
+
});
|
|
127
|
+
const record = await handleResponse(res, (x) => x);
|
|
128
|
+
return toMemory(record as Parameters<typeof toMemory>[0]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** 删除 */
|
|
132
|
+
async delete(id: string): Promise<void> {
|
|
133
|
+
const res = await fetch(this.url(`${MEMORIES_PATH}/${encodeURIComponent(id)}`), {
|
|
134
|
+
method: 'DELETE',
|
|
135
|
+
headers: this.headers(),
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok) {
|
|
138
|
+
const data = await res.json().catch(() => ({}));
|
|
139
|
+
const err = data && typeof data === 'object' && 'error' in data ? String(data.error) : `HTTP ${res.status}`;
|
|
140
|
+
throw new Error(err);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory 数据类型定义(与后端 API 返回对齐)
|
|
3
|
+
*/
|
|
4
|
+
export interface Memory {
|
|
5
|
+
id: string;
|
|
6
|
+
source: string;
|
|
7
|
+
category: string;
|
|
8
|
+
content: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
images?: string[];
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
metadata?: unknown;
|
|
14
|
+
rawData?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** 创建 Memory 的请求体:source、category、content 必填 */
|
|
18
|
+
export interface CreatePayload {
|
|
19
|
+
source: string;
|
|
20
|
+
category: string;
|
|
21
|
+
content: string;
|
|
22
|
+
tags?: string[];
|
|
23
|
+
images?: string[];
|
|
24
|
+
metadata?: unknown;
|
|
25
|
+
rawData?: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** 更新 Memory 的请求体:全部可选 */
|
|
29
|
+
export interface UpdatePayload {
|
|
30
|
+
source?: string;
|
|
31
|
+
category?: string;
|
|
32
|
+
content?: string;
|
|
33
|
+
tags?: string[];
|
|
34
|
+
images?: string[];
|
|
35
|
+
metadata?: unknown;
|
|
36
|
+
rawData?: unknown;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 列表/筛选参数(对应 GET 的 searchParams) */
|
|
40
|
+
export interface ListParams {
|
|
41
|
+
category?: string;
|
|
42
|
+
source?: string;
|
|
43
|
+
tag?: string;
|
|
44
|
+
limit?: number;
|
|
45
|
+
offset?: number;
|
|
46
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"rootDir": "./src",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"moduleResolution": "node",
|
|
15
|
+
"resolveJsonModule": true
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|