@kevisual/noco
Version:
一个轻量级的 NocoDB API SDK,支持表记录操作和 Base 管理功能。
429 lines (422 loc) • 10.1 kB
JavaScript
// src/record.ts
var stystemFields = ["nc_order", "nc_created_by", "nc_updated_by"];
class Record {
query;
table;
meta;
constructor({ query, table, meta }) {
this.query = query;
this.table = table;
this.meta = meta;
}
list(params = {}) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, {
method: "GET",
params
});
}
create(data) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, {
method: "POST",
data
});
}
read(id) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records/${id}`, {
method: "GET"
});
}
update(data) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, {
method: "PATCH",
data
});
}
delete(data) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, {
method: "DELETE",
data
});
}
count() {
return this.query.makeRequest(`/api/v2/tables/${this.table}/records/count`, {
method: "GET"
});
}
listLinks(linkFieldId, Id) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${Id}`, {
method: "GET"
});
}
updateLinks(linkFieldId, Id, data) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${Id}`, {
method: "POST",
data
});
}
deleteLinks(linkFieldId, Id) {
return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${Id}`, {
method: "DELETE"
});
}
getTableMeta() {
return this.meta.tables.getTableMeta(this.table);
}
async getTableSchema() {
const res = await this.getTableMeta();
if (res.code === 200) {
const columns = res.data.columns;
const _columns = columns.filter((col) => !stystemFields.includes(col.title)).map((col) => ({
id: col.id,
name: col.title,
type: col.uidt,
required: col.rqd,
primary: col.pv,
options: col.colOptions
}));
const schema = {};
for (const col of _columns) {
schema[col.name] = {
type: col.type,
required: col.required,
options: col.options
};
}
return {
code: 200,
data: {
columns: _columns,
schema
}
};
}
return res;
}
}
// src/api.ts
class Query {
baseURL;
token;
constructor({ baseURL, token }) {
this.baseURL = baseURL;
this.token = token;
}
makeRequest(endpoint, options) {
const url = new URL(endpoint, this.baseURL);
const isJson = options.json ?? true;
const bodyIsFormData = options.isFromData || false;
if (options.params) {
Object.entries(options.params).forEach(([key, value]) => {
url.searchParams.append(key, String(value));
});
}
const method = options.method || "GET";
const headers = {
"xc-token": `${this.token}`,
...options.headers
};
if (!bodyIsFormData) {
headers["Content-Type"] = "application/json";
}
const fetchOptions = {
method,
headers
};
if (options.body) {
fetchOptions.body = options.body;
} else if (options.data) {
fetchOptions.body = JSON.stringify(options.data);
}
return fetch(url.href, fetchOptions).then(async (response) => {
if (!response.ok) {
return { code: response.status, message: response.statusText };
}
if (isJson) {
const result = await response.json();
const isArray = Array.isArray(result);
if (isArray) {
return {
code: 200,
data: { list: result }
};
} else if (result && typeof result === "object" && !("code" in result)) {
return {
code: 200,
data: result
};
}
return result;
}
return response;
});
}
}
// src/meta/base.ts
class MetaBases {
query;
constructor(options) {
this.query = options?.query;
}
async list(workspaceId) {
return this.query.makeRequest(`/api/v2/meta/workspaces/${workspaceId}/bases`, {
method: "GET"
});
}
async create(data) {
return this.query.makeRequest("/api/v2/meta/bases", {
method: "POST",
data
});
}
async get(baseId) {
return this.query.makeRequest(`/api/v2/meta/bases/${baseId}`, {
method: "GET"
});
}
}
// src/meta/tables.ts
class MetaTables {
query;
constructor(options) {
this.query = options?.query;
}
async list(baseId) {
return this.query.makeRequest(`/api/v2/meta/bases/${baseId}/tables`, {
method: "GET"
});
}
async createTable(baseId, data) {
return this.query.makeRequest(`/api/v2/meta/bases/${baseId}/tables`, {
method: "POST",
data
});
}
async getTableMeta(tableId) {
return this.query.makeRequest(`/api/v2/meta/tables/${tableId}`, {
method: "GET"
});
}
async createColumn(tableId, data) {
return this.query.makeRequest(`/api/v2/meta/tables/${tableId}/columns`, {
method: "POST",
data
});
}
}
// src/meta/webhook.ts
class Webhook {
query;
constructor(options) {
this.query = options?.query;
}
listTableWebhooks(tableId) {
return this.query.makeRequest(`/api/v2/meta/tables/${tableId}/hooks`, {
method: "GET"
});
}
createTableWebhook(tableId, data) {
return this.query.makeRequest(`/api/v2/meta/tables/${tableId}/hooks`, {
method: "POST",
data: {
version: "v3",
event: "manual",
...data
}
});
}
updateTableWebhook(hookId, data) {
return this.query.makeRequest(`/api/v2/meta/hooks/${hookId}`, {
method: "PUT",
data
});
}
deleteTableWebhook(hookId) {
return this.query.makeRequest(`/api/v2/meta/hooks/${hookId}`, {
method: "DELETE"
});
}
}
// src/meta/index.ts
class Meta {
query;
bases;
tables;
webhooks;
constructor(options) {
this.query = options?.query;
this.bases = new MetaBases({ query: this.query });
this.tables = new MetaTables({ query: this.query });
this.webhooks = new Webhook({ query: this.query });
}
}
// src/data/upload.ts
class Upload {
query;
constructor(query) {
this.query = query;
}
async createUpload(opts) {
const formData = new FormData;
const { path, mimeType, file, size, title, url } = opts;
if (url) {
formData.append("url", url);
}
if (file) {
formData.append("file", file, title);
}
if (path) {
formData.append("path", path);
}
if (mimeType) {
formData.append("mimetype", mimeType);
}
if (size) {
formData.append("size", size.toString());
}
if (title) {
formData.append("title", title);
}
return await this.query.makeRequest("/api/v2/storage/upload", {
method: "POST",
body: formData,
isFromData: true
});
}
}
// src/main.ts
class NocoApi {
query;
record;
meta;
upload;
constructor(options) {
const table = options?.table;
const token = options?.token;
const baseURL = options?.baseURL;
this.query = new Query({ baseURL, token });
this.meta = new Meta({ query: this.query });
this.upload = new Upload(this.query);
this.record = new Record({ query: this.query, table, meta: this.meta });
}
get baseURL() {
return this.query.baseURL;
}
set baseURL(url) {
this.query.baseURL = url;
}
async getTableByName(table, baseId) {
const res = await this.meta.tables.list(baseId);
if (res.code === 200) {
const tableMeta = res.data.list.find((t) => t.table_name === table);
return tableMeta;
}
return null;
}
async createExampleTable(baseId, data) {
const defaultColumns = [
{
title: "Id",
uidt: "ID",
pk: true,
pv: true
},
{
title: "标题",
uidt: "SingleLineText",
description: "标题列"
},
{
title: "摘要",
uidt: "LongText",
description: "摘要列"
},
{
title: "标签",
uidt: "MultiSelect",
description: "标签列"
},
{
title: "描述",
uidt: "LongText",
description: "描述列"
},
{
title: "链接",
uidt: "URL",
description: "链接列"
}
];
const columns = data?.columns || [];
for (const col of defaultColumns) {
if (!columns.find((c) => c.title === col.title)) {
columns.push(col);
}
}
const res = await this.meta.tables.createTable(baseId, {
title: data?.title || "基本表",
description: data?.description || "",
columns
});
return res;
}
}
// src/meta/api-token.ts
class ApiToken {
query;
constructor(options) {
this.query = options?.query;
}
getTokenList(data) {
return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens`, {
method: "GET"
});
}
createToken(data) {
return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens`, {
method: "POST",
data
});
}
deleteToken(data) {
return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens/${data.tokenId}`, {
method: "DELETE"
});
}
}
// src/meta/users.ts
class Users {
query;
constructor(options) {
this.query = options?.query;
}
async listUsers(baseId) {
return this.query.makeRequest(`api/v1/db/meta/projects/${baseId}/users`, {
method: "GET"
});
}
async createUser(baseId, data) {
return this.query.makeRequest(`/api/v1/db/meta/projects/${baseId}/users`, {
method: "POST",
data
});
}
async deleteUser(userId) {
return this.query.makeRequest(`/api/v1/users/${userId}`, {
method: "DELETE",
headers: {
"xc-gui": "true"
}
});
}
}
export {
Webhook,
Users,
Upload,
Record,
Query,
NocoApi,
MetaBases,
Meta,
ApiToken
};