diff --git a/src/api.ts b/src/api.ts index 97abfe5..49b42b3 100644 --- a/src/api.ts +++ b/src/api.ts @@ -16,6 +16,7 @@ type MakeRequestOptions = { // body 优先级别高于 data isFromData?: boolean; body?: any; + headers?: Record; }; export class Query { baseURL: string; @@ -36,6 +37,7 @@ export class Query { const method = options.method || 'GET'; const headers: HeadersInit = { 'xc-token': `${this.token}`, + ...options.headers, }; // 如果 body 不是 FormData,才设置 Content-Type diff --git a/src/index.ts b/src/index.ts index 982420e..89e04dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,4 +8,8 @@ export * from './data/upload.ts'; // 重要的类型定义模块 export type { CreateColumnData, CreateTableData } from './meta/tables.ts'; -export type { QueryParams } from './record.ts'; \ No newline at end of file +export type { QueryParams } from './record.ts'; + +export { ApiToken } from './meta/api-token.ts'; + +export { Users } from './meta/users.ts'; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 435d5d2..5d9bf47 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,37 +23,50 @@ export class NocoApi { 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: string) { + this.query.baseURL = url; + } /** * * @param baseId * @param data */ async createExampleTable(baseId: string, data?: ExampleTableData) { - const defaultColumns = [{ - title: 'Title', - uidt: 'SingleLineText', - description: '标题列', - }, - { - title: 'Summary', - uidt: 'LongText', - description: '摘要列', - }, - { - title: 'Tags', - uidt: 'MultiSelect', - description: '标签列', - }, - { - title: 'Description', - uidt: 'LongText', - description: '描述列', - }, - { - title: 'Link', - uidt: 'URL', - description: '链接列', - }] + 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)) { diff --git a/src/meta/api-token.ts b/src/meta/api-token.ts new file mode 100644 index 0000000..b4fa3d5 --- /dev/null +++ b/src/meta/api-token.ts @@ -0,0 +1,31 @@ +import { Query } from '../api.ts'; + +export type BaseOptions = { + query: Query; +}; + + +export class ApiToken { + query: Query; + + constructor(options?: BaseOptions) { + this.query = options?.query; + } + getTokenList(data: { baseId: string }) { + return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens`, { + method: 'GET', + }); + } + createToken(data: { baseId?: string, description?: string; fk_user_id?: string }) { + // 创建 API Token + return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens`, { + method: 'POST', + data, + }); + } + deleteToken(data: { baseId: string; tokenId: string }) { + return this.query.makeRequest(`/api/v2/meta/bases/${data.baseId}/api-tokens/${data.tokenId}`, { + method: 'DELETE', + }); + } +} \ No newline at end of file diff --git a/src/meta/tables.ts b/src/meta/tables.ts index 6902679..7df2b27 100644 --- a/src/meta/tables.ts +++ b/src/meta/tables.ts @@ -68,6 +68,8 @@ export type CreateColumnData = { title: string; uidt?: ColumnTypes description?: string; + /** id 自增的必填项 */ + pk?: boolean; /** * 是否为主键 primay 的值 */ @@ -92,18 +94,43 @@ export type CreateColumnData = { meta?: Record; } export const columnTypes = [ - 'SingleLineText', - 'LongText', - 'URL', - 'Email', - 'Number', - 'SingleSelect', - 'MultiSelect', - 'DateTime', - 'Time', - 'Date', - 'Checkbox', - 'JSON' + 'SingleLineText', // 单行文本 + 'LongText', // 长文本 + 'PhoneNumber', // 电话号码 + 'Email', // 邮箱 + 'URL', // 链接 + 'Number', // 数字 + 'Decimal', // 小数 + 'Percent', // 百分比 + 'Currency', // 货币 + 'Duration', // 时长 + 'Date', // 日期 + 'Time', // 时间 + 'DateTime', // 日期时间 + 'Year', // 年份 + 'SingleSelect', // 单选 + 'MultiSelect', // 多选 + 'User', // 用户 + 'Attachment', // 附件 + 'Checkbox', // 复选框 + 'Rating', // 评分 + 'Button', // 按钮 + 'Formula', // 公式 + 'Barcode', // 条形码 + 'QRCode', // 二维码 + 'Links', // 链接关系 + 'LinkToAnotherRecord', // 关联记录 + 'Lookup', // 查找 + 'Rollup', // 汇总 + 'ID', // ID + 'CreatedTime', // 创建时间 + 'LastModifiedTime', // 最后修改时间 + 'CreatedBy', // 创建者 + 'LastModifiedBy', // 最后修改者 + 'GeoData', // 地理数据 + 'Geometry', // 几何图形 + 'JSON', // JSON + 'SpecificDBType' // 特定数据库类型 ] as const; export type ColumnTypes = typeof columnTypes[number]; diff --git a/src/meta/users.ts b/src/meta/users.ts new file mode 100644 index 0000000..7f7ac43 --- /dev/null +++ b/src/meta/users.ts @@ -0,0 +1,49 @@ +import { Query, ResponseList } from '../api.ts'; + +type Options = { + query: Query; +}; + +export class Users { + query?: Query; + constructor(options?: Options) { + this.query = options?.query; + } + async listUsers(baseId?: string): Promise> { + // return this.query.makeRequest(`/api/v2/meta/bases/${baseId}/users`, { + // method: 'GET', + // }); + return this.query.makeRequest(`api/v1/db/meta/projects/${baseId}/users`, { + method: 'GET', + }); + } + async createUser(baseId: string, data: Partial): Promise { + // return this.query.makeRequest(`/api/v2/meta/bases/${baseId}/users`, { + return this.query.makeRequest(`/api/v1/db/meta/projects/${baseId}/users`, { + method: 'POST', + data, + }); + } + async deleteUser(userId: string): Promise<{ code: number; message: string }> { + // return this.query.makeRequest(`/api/v2/meta/bases/${baseId}/users/${userId}`, { + return this.query.makeRequest(`/api/v1/users/${userId}`, { + method: 'DELETE', + headers: { + 'xc-gui': 'true' + } + }); + } +} +const userRoles = ['no-access', 'commenter', 'editor', 'guest', 'owner', 'viewer', 'creator'] as const; +type UserRole = typeof userRoles[number]; +type UserItem = { + email: string; + display_name: string; + invite_token: string; + id: string; + meta?: any; + main_roles?: string;// org-level-creator,super + base_id?: string; + roles: UserRole; + created_at: string; +}; diff --git a/test/common.ts b/test/common.ts index 115451f..18218c6 100644 --- a/test/common.ts +++ b/test/common.ts @@ -1,9 +1,10 @@ -import { NocoApi } from './../src/main.ts'; +import { NocoApi, } from './../src/main.ts'; import { useConfig } from '@kevisual/use-config' import { CreateBaseData } from '../src/meta/index.ts'; export const config = useConfig() import util from 'node:util'; import { writeFile, writeFileSync } from 'node:fs'; +import { ApiToken, Users } from "./../src/index.ts" // # 签到表 // const table = 'mcby44q8zrayvn9' // 本地 @@ -14,12 +15,23 @@ export const nocoApi = new NocoApi({ table, }); +export const apiToken = new ApiToken({ + query: nocoApi.query, +}); +export const showMore = (obj: any) => { + return util.inspect(obj, { depth: null, colors: true }); +} // const res = await nocoApi.record.list() // console.log(util.inspect(res.data, { depth: null, colors: true })) -const res =await nocoApi.record.getTableMeta() -// console.log(util.inspect(res, { depth: null, colors: true })) -const keys = Object.keys(res.data || {}) -console.log('表字段列表:', keys); -writeFileSync('table-metadata.json', JSON.stringify(res, null, 2)); \ No newline at end of file +// const res = await nocoApi.record.getTableMeta() +// // console.log(util.inspect(res, { depth: null, colors: true })) +// const keys = Object.keys(res.data || {}) +// console.log('表字段列表:', keys); +// writeFileSync('table-metadata.json', JSON.stringify(res, null, 2)); + + +export const users = new Users({ + query: nocoApi.query, +}); \ No newline at end of file diff --git a/test/token.ts b/test/token.ts new file mode 100644 index 0000000..8d14c8b --- /dev/null +++ b/test/token.ts @@ -0,0 +1,41 @@ +import { NocoApi, } from '../src/main.ts'; +import { apiToken, showMore, nocoApi, config, users } from './common.ts' + +const baseId = 'pypv3deh9qzol7q' // ai table base +const fk_user_id = 'usmdq13auglrp3w2';// +// const create = await apiToken.createToken({ baseId: baseId, description: '测试创建的 Token 用fk_user_id', fk_user_id }) +// console.log('创建的 Token 信息:') +// console.log(showMore(create)) +// id: 3 + +const main = async () => { + + const aiTableToken = 'tetes' + + const linkBaseId = 'pdzc3q50vwnng5r' + const linkTable = 'mxxwx8v5i45wd7o' + const nocoApi2 = new NocoApi({ + baseURL: config.NOCODB_URL || 'http://localhost:8080', + token: aiTableToken, + table: linkTable, + }); + const res = await nocoApi2.record.list() + + console.log(showMore(res)) +} +// main() + +const userLIST = await users.listUsers(baseId) +console.log(showMore(userLIST)) + +// const user = await users.createUser(baseId, { +// email: 'kevisual@xiongxiao.me', +// roles: 'guest', +// }) + +// console.log('创建用户结果:') +// console.log(showMore(user)) + +const user = await users.deleteUser('usj8qbcns1uqm3ti') +console.log('删除用户结果:') +console.log(showMore(user)) \ No newline at end of file