From 788c7f670ac4f9571d64cca95a83a5ce4a970948 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Mon, 11 Aug 2025 00:56:06 +0800 Subject: [PATCH] update --- package.json | 1 + readme.md | 13 +++++- src/api.ts | 31 +++++++++----- src/base.ts | 114 ++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 142 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 861a6f8..b70fbc1 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "main": "index.js", "scripts": { + "watch": "bun bun.config.mjs watch", "build": " bun bun.config.mjs" }, "publishConfig": { diff --git a/readme.md b/readme.md index 2e25904..c5ae1a9 100644 --- a/readme.md +++ b/readme.md @@ -1 +1,12 @@ -# nocodb api sdk \ No newline at end of file +# nocodb api sdk + +```ts +const nocoAPi = new NocoApi({ + baseURL: config.NOCODB_URL, + token: config.NOCODB_API_KEY, +}); + +const listResult = await nocoAPi.record.list(); + +await nocoAPi.record.update({ id: 1, Title: '123' }); +``` diff --git a/src/api.ts b/src/api.ts index 79c683a..3ca32cc 100644 --- a/src/api.ts +++ b/src/api.ts @@ -11,17 +11,19 @@ type FetchOptions = { type MakeRequestOptions = { params?: Record; data?: Record; - method?: 'GET' | 'POST'; + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + json?: boolean; }; export class Query { - baseUrl: string; + baseURL: string; token: string; - constructor({ baseUrl, token }: { baseUrl: string; token: string }) { - this.baseUrl = baseUrl; + constructor({ baseURL, token }: { baseURL: string; token: string }) { + this.baseURL = baseURL; this.token = token; } makeRequest(endpoint: string, options: MakeRequestOptions) { - const url = new URL(endpoint, this.baseUrl); + const url = new URL(endpoint, this.baseURL); + const isJson = options.json ?? true; if (options.params) { Object.entries(options.params).forEach(([key, value]) => { url.searchParams.append(key, String(value)); @@ -31,16 +33,25 @@ export class Query { const headers: HeadersInit = { 'xc-token': `${this.token}`, }; - if (method === 'POST') { - headers['Content-Type'] = 'application/json'; - } + headers['Content-Type'] = 'application/json'; const fetchOptions: FetchOptions = { method, headers, }; - if (method === 'POST' && options.data) { + if (options.data) { fetchOptions.body = JSON.stringify(options.data); } - return fetch(url, fetchOptions); + console.log(url.href, fetchOptions); + 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(); + result.code = 200; + return result; + } + return response; + }); } } diff --git a/src/base.ts b/src/base.ts index cc4f468..d7838a7 100644 --- a/src/base.ts +++ b/src/base.ts @@ -3,15 +3,117 @@ import { Query } from './api.ts'; type NocoApiOptions = { table?: string; token?: string; - baseUrl?: string; + baseURL?: string; }; export class NocoApi { - table?: string; - query?: Query; + query: Query; + record: Record; constructor(options?: NocoApiOptions) { - this.table = options.table; + const table = options.table; const token = options.token; - const baseUrl = options.baseUrl; - this.query = new Query({ baseUrl, token }); + const baseURL = options.baseURL; + this.query = new Query({ baseURL, token }); + this.record = new Record(this.query, table); + } +} +type QueryParams = { + /** + * fields=field1,field2 + */ + fields?: string | string[]; + /** + * sort=field1,-field2 + */ + sort?: string | string[]; + /** + * where=(field1,eq,value1)~and(field2,eq,value2) + */ + where?: string; + offset?: number; + limit?: number; + viewId?: string; + [key: string]: any; +}; +type ResultList = { + code: number; + list: T[]; + pageInfo?: { + totalRows?: number; + page?: number; + pageSize?: number; + isFirstPage?: boolean; + isLastPage?: boolean; + }; +}; +type Id = string | number; +/** + * @url https://nocodb.com/apis/v2/data#tag/Table-Records + */ +class Record { + query: Query; + table: string; + constructor(query: Query, table: string) { + this.query = query; + this.table = table; + } + list(params: QueryParams = {}): Promise> { + return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, { + method: 'GET', + params, + }); + } + create(data: any) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, { + method: 'POST', + data, + }); + } + read(id: Id) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/records/${id}`, { + method: 'GET', + }); + } + update(data: { id: Id; [key: string]: any }) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/records`, { + method: 'PATCH', + data, + }); + } + delete(data: { id: Id }) { + 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, id: Id) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${id}`, { + method: 'GET', + }); + } + updateLinks(linkFieldId: Id, id: Id, data: any) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${id}`, { + method: 'POST', + data, + }); + } + deleteLinks(linkFieldId: Id, id: Id) { + return this.query.makeRequest(`/api/v2/tables/${this.table}/links/${linkFieldId}/records/${id}`, { + method: 'DELETE', + }); + } +} + +/** + * @url https://nocodb.com/apis/v2/meta + */ +class Meta { + bases: string; + constructor() { + this.bases = ''; } }