@amaster.ai/entity-client 1.0.0-alpha.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amaster Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @amaster.ai/entity-client
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var httpClient=require('@amaster.ai/http-client');function c(s){let e;if(s instanceof Date?e=s:typeof s=="string"?e=new Date(s):e=new Date(s),Number.isNaN(e.getTime()))return String(s);let o=e.getUTCFullYear(),r=String(e.getUTCMonth()+1).padStart(2,"0"),n=String(e.getUTCDate()).padStart(2,"0"),t=String(e.getUTCHours()).padStart(2,"0"),i=String(e.getUTCMinutes()).padStart(2,"0"),a=String(e.getUTCSeconds()).padStart(2,"0");return `${o}-${r}-${n} ${t}:${i}:${a}`}function g(s){if(s==null)return s;if(s instanceof Date)return c(s);if(Array.isArray(s))return s.map(e=>g(e));if(typeof s=="object"){let e={};for(let[o,r]of Object.entries(s))e[o]=g(r);return e}return typeof s=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(s)?c(s):s}function u(s,e,o=""){let r=`/api/entity/data/${s}/${e}`;return o?`${r}${o.startsWith("/")?o:`/${o}`}`:r}function d(s){if(!s||Object.keys(s).length===0)return "";let e=new URLSearchParams;for(let[r,n]of Object.entries(s))if(n!=null)if(r==="__filter"&&typeof n=="object")e.append(r,JSON.stringify(n));else if(r==="__relations"&&Array.isArray(n))for(let t of n)e.append("__relations[]",String(t));else if(r==="__fields"&&Array.isArray(n))n.forEach((t,i)=>{e.append(`__fields[${i}]`,String(t));});else if(r==="__keywords"&&typeof n=="object"&&!Array.isArray(n)){let t=n;if(t.fields&&t.fields.length>0&&t.value){let i=t.fields.join(",");e.append(`__keywords[${i}]`,t.value);}}else if(Array.isArray(n))for(let t of n)e.append(r,String(t));else if(typeof n=="object"&&!Array.isArray(n)){for(let[t,i]of Object.entries(n))if(i!=null)if(typeof i=="object"&&!Array.isArray(i))for(let[a,l]of Object.entries(i))l!=null&&e.append(`${r}[${t}][${a}]`,String(l));else Array.isArray(i)?i.forEach((a,l)=>{e.append(`${r}[${t}][${l}]`,String(a));}):e.append(`${r}[${t}]`,String(i));}else e.append(r,String(n));let o=e.toString();return o?`?${o}`:""}function p(s=httpClient.createHttpClient()){return {async list(e,o,r){let n=u(e,o)+d(r),t=await s.request({url:n,method:"get"});if(t.error||!t.data)return {data:{items:[],total:0},error:t.error,status:t.status};let i=Array.isArray(t.data.items)?t.data.items:[],a=t.data.total??t.data.count??i.length;return {...t,data:{items:i,total:a,page:t.data.page,perPage:t.data.perPage||t.data.pageSize}}},get(e,o,r){if(!r)return Promise.resolve({data:null,error:{message:"Entity ID is required",status:400},status:400});let n=u(e,o,`/${r}`);return s.request({url:n,method:"get"})},create(e,o,r){if(!r||typeof r!="object")return Promise.resolve({data:null,error:{message:"Entity data is required",status:400},status:400});let n=g(r),t=u(e,o);return s.request({url:t,method:"post",headers:{"Content-Type":"application/json"},data:n})},update(e,o,r,n){if(!r)return Promise.resolve({data:null,error:{message:"Entity ID is required",status:400},status:400});if(!n||typeof n!="object")return Promise.resolve({data:null,error:{message:"Entity data is required",status:400},status:400});let t=g(n),i=u(e,o,`/${r}`);return s.request({url:i,method:"put",headers:{"Content-Type":"application/json"},data:t})},async delete(e,o,r){if(!r)return {data:null,error:{message:"Entity ID is required",status:400},status:400};let n=u(e,o,`/${r}`),t=await s.request({url:n,method:"delete"});return t.status===204?{...t,data:null}:t},async options(e,o,r){let n=r&&r.length>0?{"__fields[]":r}:void 0,t=u(e,o,"/options")+d(n),i=await s.request({url:t,method:"get"});return i.error||!i.data?{data:null,error:i.error,status:i.status}:{...i,data:i.data.items||[]}},bulkUpdate(e,o,r){if(!r||r.length===0)return Promise.resolve({data:null,error:{message:"Items array is required",status:400},status:400});let n=r.map(i=>g(i)),t=u(e,o,"/bulkUpdate");return s.request({url:t,method:"post",headers:{"Content-Type":"application/json"},data:{items:n}})},async bulkDelete(e,o,r){if(!r||r.length===0)return {data:null,error:{message:"IDs array is required",status:400},status:400};let n=u(e,o,`/${r.join(",")}`),t=await s.request({url:n,method:"delete"});return t.status===204?{...t,data:null}:t}}}exports.createEntityClient=p;//# sourceMappingURL=index.cjs.map
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/entity-client.ts"],"names":["formatDateForBackend","date","dateObj","year","month","day","hours","minutes","seconds","processDataForBackend","data","item","processed","key","value","buildEntityUrl","source","entity","path","basePath","encodeQueryParams","params","searchParams","v","kw","fieldsKey","subKey","subValue","innerKey","innerValue","i","query","createEntityClient","http","createHttpClient","url","result","items","total","id","processedData","fields","processedItems","ids"],"mappings":"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","file":"index.cjs","sourcesContent":["import { type ClientResult, createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport type { EntityListResponse, EntityQueryParams } from \"./types\";\n\n// Export types for convenience\nexport type {\n AdvancedFilterOperator,\n BetweenValue,\n EntityListResponse,\n EntityQueryParams,\n FilterGroup,\n FilterItem,\n FilterOperator,\n KeywordsSearch,\n} from \"./types\";\n\n/**\n * Entity Client - Type-safe client for entity CRUD operations\n *\n * ## Quick Start\n * ```typescript\n * const entityClient = createEntityClient();\n *\n * // List with pagination and sorting\n * const result = await entityClient.list('default', 'tasks', {\n * page: 1,\n * perPage: 20,\n * orderBy: 'createdAt',\n * orderDir: 'desc'\n * });\n *\n * // ⚠️ IMPORTANT: Access items via result.data.items, NOT result.data\n * setTasks(result.data?.items || []); // ✅ Correct\n * setTotal(result.data?.total || 0);\n *\n * // ❌ WRONG: setTasks(result.data || []) - result.data is an object, not an array!\n *\n * // Get single record\n * const task = await entityClient.get('default', 'tasks', 1);\n * setTask(result.data); // ✅ result.data is the entity object directly\n *\n * // CRUD operations\n * await entityClient.create('default', 'tasks', { title: 'New', dueDate: new Date() });\n * await entityClient.update('default', 'tasks', 1, { status: 'done' });\n * await entityClient.delete('default', 'tasks', 1);\n * ```\n *\n * ## Date Handling\n * Date values are automatically converted to backend-compatible format:\n * - Date objects: `new Date()` → `\"2026-01-05 10:30:45\"`\n * - ISO 8601 strings: `\"2026-01-05T00:00:00.000Z\"` → `\"2026-01-05 00:00:00\"`\n * - Works in nested objects and arrays\n *\n * ## Filter Operators\n * eq, ne, gt, ge, lt, le, like, sw, ew, bt, in\n *\n * Usage: `{ 'field[op]': value }` or `{ field: value }` (eq is default)\n */\nexport type EntityClient = {\n list<T = Record<string, unknown>>(\n source: string,\n entity: string,\n params?: EntityQueryParams\n ): Promise<ClientResult<EntityListResponse<T>>>;\n get<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number\n ): Promise<ClientResult<T>>;\n create<T = Record<string, unknown>>(\n source: string,\n entity: string,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>>;\n update<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>>;\n delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>>;\n options<T = Record<string, unknown>>(\n source: string,\n entity: string,\n fields?: string[]\n ): Promise<ClientResult<T[]>>;\n bulkUpdate<T = Record<string, unknown>>(\n source: string,\n entity: string,\n items: Array<Record<string, unknown> & { id: string | number }>\n ): Promise<ClientResult<T>>;\n bulkDelete(\n source: string,\n entity: string,\n ids: Array<string | number>\n ): Promise<ClientResult<null>>;\n};\n\n// ==================== Helper Functions ====================\n\n/**\n * Convert Date object or ISO 8601 string to backend-compatible DATETIME format\n * Backend expects: \"YYYY-MM-DD HH:MM:SS\" (space-separated, no T or Z)\n */\nfunction formatDateForBackend(date: Date | string): string {\n let dateObj: Date;\n\n if (date instanceof Date) {\n dateObj = date;\n } else if (typeof date === \"string\") {\n dateObj = new Date(date);\n } else {\n dateObj = new Date(date);\n }\n\n // Check if date is valid\n if (Number.isNaN(dateObj.getTime())) {\n return String(date); // Return original value if invalid\n }\n\n // Format as \"YYYY-MM-DD HH:MM:SS\" in UTC\n const year = dateObj.getUTCFullYear();\n const month = String(dateObj.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(dateObj.getUTCDate()).padStart(2, \"0\");\n const hours = String(dateObj.getUTCHours()).padStart(2, \"0\");\n const minutes = String(dateObj.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(dateObj.getUTCSeconds()).padStart(2, \"0\");\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Recursively process data object to convert Date values to backend format\n * Handles nested objects and arrays\n */\nfunction processDataForBackend(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle Date objects\n if (data instanceof Date) {\n return formatDateForBackend(data);\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processDataForBackend(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processDataForBackend(value);\n }\n return processed;\n }\n\n // Handle ISO 8601 date strings (detect pattern)\n if (typeof data === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(data)) {\n return formatDateForBackend(data);\n }\n\n return data;\n}\n\nfunction buildEntityUrl(source: string, entity: string, path = \"\"): string {\n const basePath = `/api/entity/data/${source}/${entity}`;\n return path ? `${basePath}${path.startsWith(\"/\") ? path : `/${path}`}` : basePath;\n}\n\nfunction encodeQueryParams(params?: Record<string, unknown>): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (key === \"__filter\" && typeof value === \"object\") {\n // Advanced filter: JSON stringify\n searchParams.append(key, JSON.stringify(value));\n } else if (key === \"__relations\" && Array.isArray(value)) {\n // Relations: array format\n for (const v of value) {\n searchParams.append(\"__relations[]\", String(v));\n }\n } else if (key === \"__fields\" && Array.isArray(value)) {\n // Fields selection: indexed array format\n value.forEach((v, i) => {\n searchParams.append(`__fields[${i}]`, String(v));\n });\n } else if (key === \"__keywords\" && typeof value === \"object\" && !Array.isArray(value)) {\n // Keywords search with specific fields: __keywords[field1,field2]=value\n const kw = value as { fields?: string[]; value?: string };\n if (kw.fields && kw.fields.length > 0 && kw.value) {\n const fieldsKey = kw.fields.join(\",\");\n searchParams.append(`__keywords[${fieldsKey}]`, kw.value);\n }\n } else if (Array.isArray(value)) {\n // Generic array\n for (const v of value) {\n searchParams.append(key, String(v));\n }\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // Object: nested format (e.g., field[op]=value or field[bt]={from,to})\n for (const [subKey, subValue] of Object.entries(value)) {\n if (subValue !== undefined && subValue !== null) {\n if (typeof subValue === \"object\" && !Array.isArray(subValue)) {\n // Handle nested object like { bt: { from: x, to: y } }\n for (const [innerKey, innerValue] of Object.entries(subValue)) {\n if (innerValue !== undefined && innerValue !== null) {\n searchParams.append(`${key}[${subKey}][${innerKey}]`, String(innerValue));\n }\n }\n } else if (Array.isArray(subValue)) {\n // Handle array in object like { in: [1,2,3] }\n subValue.forEach((v, i) => {\n searchParams.append(`${key}[${subKey}][${i}]`, String(v));\n });\n } else {\n searchParams.append(`${key}[${subKey}]`, String(subValue));\n }\n }\n }\n } else {\n searchParams.append(key, String(value));\n }\n }\n\n const query = searchParams.toString();\n return query ? `?${query}` : \"\";\n}\n\n// ==================== Client Factory ====================\n\nexport function createEntityClient(http: HttpClient = createHttpClient()): EntityClient {\n return {\n async list<T = Record<string, unknown>>(\n source: string,\n entity: string,\n params?: EntityQueryParams\n ): Promise<ClientResult<EntityListResponse<T>>> {\n const url = buildEntityUrl(source, entity) + encodeQueryParams(params);\n const result = await http.request<{\n items: T[];\n count?: number;\n total?: number;\n page?: number;\n perPage?: number;\n pageSize?: number;\n }>({\n url,\n method: \"get\",\n });\n\n if (result.error || !result.data) {\n return {\n data: { items: [], total: 0 },\n error: result.error,\n status: result.status,\n };\n }\n\n const items = Array.isArray(result.data.items) ? result.data.items : [];\n const total = result.data.total ?? result.data.count ?? items.length;\n\n return {\n ...result,\n data: {\n items,\n total,\n page: result.data.page,\n perPage: result.data.perPage || result.data.pageSize,\n },\n };\n },\n\n get<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number\n ): Promise<ClientResult<T>> {\n if (!id) {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n });\n }\n const url = buildEntityUrl(source, entity, `/${id}`);\n return http.request<T>({\n url,\n method: \"get\",\n });\n },\n\n create<T = Record<string, unknown>>(\n source: string,\n entity: string,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>> {\n if (!data || typeof data !== \"object\") {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity data is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedData = processDataForBackend(data);\n\n const url = buildEntityUrl(source, entity);\n return http.request<T>({\n url,\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: processedData,\n });\n },\n\n update<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>> {\n if (!id) {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n });\n }\n if (!data || typeof data !== \"object\") {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity data is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedData = processDataForBackend(data);\n\n const url = buildEntityUrl(source, entity, `/${id}`);\n return http.request<T>({\n url,\n method: \"put\",\n headers: { \"Content-Type\": \"application/json\" },\n data: processedData,\n });\n },\n\n async delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>> {\n if (!id) {\n return {\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n };\n }\n const url = buildEntityUrl(source, entity, `/${id}`);\n const result = await http.request<null>({\n url,\n method: \"delete\",\n });\n return result.status === 204 ? { ...result, data: null } : result;\n },\n\n async options<T = Record<string, unknown>>(\n source: string,\n entity: string,\n fields?: string[]\n ): Promise<ClientResult<T[]>> {\n const params = fields && fields.length > 0 ? { \"__fields[]\": fields } : undefined;\n\n const url = buildEntityUrl(source, entity, \"/options\") + encodeQueryParams(params);\n const result = await http.request<{ items: T[] }>({\n url,\n method: \"get\",\n });\n\n if (result.error || !result.data) {\n return {\n data: null,\n error: result.error,\n status: result.status,\n };\n }\n\n return {\n ...result,\n data: result.data.items || [],\n };\n },\n\n bulkUpdate<T = Record<string, unknown>>(\n source: string,\n entity: string,\n items: Array<Record<string, unknown> & { id: string | number }>\n ): Promise<ClientResult<T>> {\n if (!items || items.length === 0) {\n return Promise.resolve({\n data: null,\n error: { message: \"Items array is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedItems = items.map((item) => processDataForBackend(item));\n\n const url = buildEntityUrl(source, entity, \"/bulkUpdate\");\n return http.request<T>({\n url,\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { items: processedItems },\n });\n },\n\n async bulkDelete(\n source: string,\n entity: string,\n ids: Array<string | number>\n ): Promise<ClientResult<null>> {\n if (!ids || ids.length === 0) {\n return {\n data: null,\n error: { message: \"IDs array is required\", status: 400 },\n status: 400,\n };\n }\n\n const url = buildEntityUrl(source, entity, `/${ids.join(\",\")}`);\n const result = await http.request<null>({\n url,\n method: \"delete\",\n });\n\n return result.status === 204 ? { ...result, data: null } : result;\n },\n };\n}\n"]}
@@ -0,0 +1,176 @@
1
+ import { ClientResult, HttpClient } from '@amaster.ai/http-client';
2
+
3
+ /**
4
+ * Entity Client Type Definitions
5
+ */
6
+ /**
7
+ * Simple filter operators (used in query string format: field[op]=value)
8
+ *
9
+ * @example
10
+ * { 'status[eq]': 'active' } // status = 'active'
11
+ * { 'price[gt]': 100 } // price > 100
12
+ * { 'name[like]': 'test' } // name LIKE '%test%'
13
+ * { 'id[in]': [1, 2, 3] } // id IN (1, 2, 3)
14
+ */
15
+ type FilterOperator = "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "like" | "sw" | "ew" | "bt" | "in";
16
+ /**
17
+ * Advanced filter operators (used in __filter JSON format)
18
+ *
19
+ * @example
20
+ * { op: 'equal', left: { field: 'status' }, right: 'active' }
21
+ * { op: 'like', left: { field: 'name' }, right: 'test' } // auto wraps with %
22
+ */
23
+ type AdvancedFilterOperator = "equal" | "not_equal" | "less" | "less_or_equal" | "greater" | "greater_or_equal" | "like" | "not_like" | "starts_with" | "ends_with" | "between" | "is_empty" | "is_not_empty" | "select_any_in" | "select_not_any_in";
24
+ /**
25
+ * Advanced filter item (single condition)
26
+ */
27
+ type FilterItem = {
28
+ op: AdvancedFilterOperator;
29
+ left: {
30
+ field: string;
31
+ };
32
+ right?: string | number | boolean | Date | null | string[] | number[];
33
+ };
34
+ /**
35
+ * Advanced filter group (supports AND/OR combinations with nesting)
36
+ *
37
+ * @example
38
+ * // (status = 'active') AND (priority > 5 OR assignee IS NOT NULL)
39
+ * {
40
+ * conjunction: 'and',
41
+ * children: [
42
+ * { op: 'equal', left: { field: 'status' }, right: 'active' },
43
+ * {
44
+ * conjunction: 'or',
45
+ * children: [
46
+ * { op: 'greater', left: { field: 'priority' }, right: 5 },
47
+ * { op: 'is_not_empty', left: { field: 'assignee' } }
48
+ * ]
49
+ * }
50
+ * ]
51
+ * }
52
+ */
53
+ type FilterGroup = {
54
+ conjunction: "and" | "or";
55
+ children: Array<FilterGroup | FilterItem>;
56
+ };
57
+ /**
58
+ * Keywords search configuration
59
+ *
60
+ * @example
61
+ * // Search in specific fields
62
+ * { fields: ['name', 'description'], value: 'search term' }
63
+ *
64
+ * // Or use string format for simple search (backend determines searchable fields)
65
+ * '__keywords': 'search term'
66
+ */
67
+ type KeywordsSearch = {
68
+ fields: string[];
69
+ value: string;
70
+ };
71
+ /**
72
+ * Entity query parameters
73
+ *
74
+ * @example
75
+ * // Basic pagination and sorting
76
+ * { page: 1, perPage: 20, orderBy: 'created_at', orderDir: 'desc' }
77
+ *
78
+ * // Keywords search in specific fields
79
+ * { __keywords: { fields: ['name', 'description'], value: 'search' } }
80
+ *
81
+ * // Simple field filter
82
+ * { status: 'active', 'price[gt]': 100 }
83
+ *
84
+ * // Advanced filter with AND/OR
85
+ * { __filter: { conjunction: 'and', children: [...] } }
86
+ *
87
+ * // Load relations
88
+ * { __relations: ['user', 'category'] }
89
+ *
90
+ * // Select specific fields
91
+ * { __fields: ['id', 'name', 'status'] }
92
+ *
93
+ * // Multiple orders
94
+ * { __orders: 'priority:desc,created_at:asc' }
95
+ */
96
+ type EntityQueryParams = {
97
+ page?: number;
98
+ perPage?: number;
99
+ limit?: number;
100
+ offset?: number;
101
+ orderBy?: string;
102
+ orderDir?: "asc" | "desc";
103
+ __orders?: string;
104
+ __keywords?: string | KeywordsSearch;
105
+ __relations?: string[];
106
+ __fields?: string[];
107
+ __filter?: FilterGroup;
108
+ [key: string]: unknown;
109
+ };
110
+ /**
111
+ * Entity list response
112
+ */
113
+ type EntityListResponse<T = Record<string, unknown>> = {
114
+ items: T[];
115
+ total: number;
116
+ page?: number;
117
+ perPage?: number;
118
+ };
119
+
120
+ /**
121
+ * Entity Client - Type-safe client for entity CRUD operations
122
+ *
123
+ * ## Quick Start
124
+ * ```typescript
125
+ * const entityClient = createEntityClient();
126
+ *
127
+ * // List with pagination and sorting
128
+ * const result = await entityClient.list('default', 'tasks', {
129
+ * page: 1,
130
+ * perPage: 20,
131
+ * orderBy: 'createdAt',
132
+ * orderDir: 'desc'
133
+ * });
134
+ *
135
+ * // ⚠️ IMPORTANT: Access items via result.data.items, NOT result.data
136
+ * setTasks(result.data?.items || []); // ✅ Correct
137
+ * setTotal(result.data?.total || 0);
138
+ *
139
+ * // ❌ WRONG: setTasks(result.data || []) - result.data is an object, not an array!
140
+ *
141
+ * // Get single record
142
+ * const task = await entityClient.get('default', 'tasks', 1);
143
+ * setTask(result.data); // ✅ result.data is the entity object directly
144
+ *
145
+ * // CRUD operations
146
+ * await entityClient.create('default', 'tasks', { title: 'New', dueDate: new Date() });
147
+ * await entityClient.update('default', 'tasks', 1, { status: 'done' });
148
+ * await entityClient.delete('default', 'tasks', 1);
149
+ * ```
150
+ *
151
+ * ## Date Handling
152
+ * Date values are automatically converted to backend-compatible format:
153
+ * - Date objects: `new Date()` → `"2026-01-05 10:30:45"`
154
+ * - ISO 8601 strings: `"2026-01-05T00:00:00.000Z"` → `"2026-01-05 00:00:00"`
155
+ * - Works in nested objects and arrays
156
+ *
157
+ * ## Filter Operators
158
+ * eq, ne, gt, ge, lt, le, like, sw, ew, bt, in
159
+ *
160
+ * Usage: `{ 'field[op]': value }` or `{ field: value }` (eq is default)
161
+ */
162
+ type EntityClient = {
163
+ list<T = Record<string, unknown>>(source: string, entity: string, params?: EntityQueryParams): Promise<ClientResult<EntityListResponse<T>>>;
164
+ get<T = Record<string, unknown>>(source: string, entity: string, id: string | number): Promise<ClientResult<T>>;
165
+ create<T = Record<string, unknown>>(source: string, entity: string, data: Record<string, unknown>): Promise<ClientResult<T>>;
166
+ update<T = Record<string, unknown>>(source: string, entity: string, id: string | number, data: Record<string, unknown>): Promise<ClientResult<T>>;
167
+ delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>>;
168
+ options<T = Record<string, unknown>>(source: string, entity: string, fields?: string[]): Promise<ClientResult<T[]>>;
169
+ bulkUpdate<T = Record<string, unknown>>(source: string, entity: string, items: Array<Record<string, unknown> & {
170
+ id: string | number;
171
+ }>): Promise<ClientResult<T>>;
172
+ bulkDelete(source: string, entity: string, ids: Array<string | number>): Promise<ClientResult<null>>;
173
+ };
174
+ declare function createEntityClient(http?: HttpClient): EntityClient;
175
+
176
+ export { type EntityClient, type EntityListResponse, type EntityQueryParams, type FilterGroup, type FilterItem, type FilterOperator, createEntityClient };
@@ -0,0 +1,176 @@
1
+ import { ClientResult, HttpClient } from '@amaster.ai/http-client';
2
+
3
+ /**
4
+ * Entity Client Type Definitions
5
+ */
6
+ /**
7
+ * Simple filter operators (used in query string format: field[op]=value)
8
+ *
9
+ * @example
10
+ * { 'status[eq]': 'active' } // status = 'active'
11
+ * { 'price[gt]': 100 } // price > 100
12
+ * { 'name[like]': 'test' } // name LIKE '%test%'
13
+ * { 'id[in]': [1, 2, 3] } // id IN (1, 2, 3)
14
+ */
15
+ type FilterOperator = "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "like" | "sw" | "ew" | "bt" | "in";
16
+ /**
17
+ * Advanced filter operators (used in __filter JSON format)
18
+ *
19
+ * @example
20
+ * { op: 'equal', left: { field: 'status' }, right: 'active' }
21
+ * { op: 'like', left: { field: 'name' }, right: 'test' } // auto wraps with %
22
+ */
23
+ type AdvancedFilterOperator = "equal" | "not_equal" | "less" | "less_or_equal" | "greater" | "greater_or_equal" | "like" | "not_like" | "starts_with" | "ends_with" | "between" | "is_empty" | "is_not_empty" | "select_any_in" | "select_not_any_in";
24
+ /**
25
+ * Advanced filter item (single condition)
26
+ */
27
+ type FilterItem = {
28
+ op: AdvancedFilterOperator;
29
+ left: {
30
+ field: string;
31
+ };
32
+ right?: string | number | boolean | Date | null | string[] | number[];
33
+ };
34
+ /**
35
+ * Advanced filter group (supports AND/OR combinations with nesting)
36
+ *
37
+ * @example
38
+ * // (status = 'active') AND (priority > 5 OR assignee IS NOT NULL)
39
+ * {
40
+ * conjunction: 'and',
41
+ * children: [
42
+ * { op: 'equal', left: { field: 'status' }, right: 'active' },
43
+ * {
44
+ * conjunction: 'or',
45
+ * children: [
46
+ * { op: 'greater', left: { field: 'priority' }, right: 5 },
47
+ * { op: 'is_not_empty', left: { field: 'assignee' } }
48
+ * ]
49
+ * }
50
+ * ]
51
+ * }
52
+ */
53
+ type FilterGroup = {
54
+ conjunction: "and" | "or";
55
+ children: Array<FilterGroup | FilterItem>;
56
+ };
57
+ /**
58
+ * Keywords search configuration
59
+ *
60
+ * @example
61
+ * // Search in specific fields
62
+ * { fields: ['name', 'description'], value: 'search term' }
63
+ *
64
+ * // Or use string format for simple search (backend determines searchable fields)
65
+ * '__keywords': 'search term'
66
+ */
67
+ type KeywordsSearch = {
68
+ fields: string[];
69
+ value: string;
70
+ };
71
+ /**
72
+ * Entity query parameters
73
+ *
74
+ * @example
75
+ * // Basic pagination and sorting
76
+ * { page: 1, perPage: 20, orderBy: 'created_at', orderDir: 'desc' }
77
+ *
78
+ * // Keywords search in specific fields
79
+ * { __keywords: { fields: ['name', 'description'], value: 'search' } }
80
+ *
81
+ * // Simple field filter
82
+ * { status: 'active', 'price[gt]': 100 }
83
+ *
84
+ * // Advanced filter with AND/OR
85
+ * { __filter: { conjunction: 'and', children: [...] } }
86
+ *
87
+ * // Load relations
88
+ * { __relations: ['user', 'category'] }
89
+ *
90
+ * // Select specific fields
91
+ * { __fields: ['id', 'name', 'status'] }
92
+ *
93
+ * // Multiple orders
94
+ * { __orders: 'priority:desc,created_at:asc' }
95
+ */
96
+ type EntityQueryParams = {
97
+ page?: number;
98
+ perPage?: number;
99
+ limit?: number;
100
+ offset?: number;
101
+ orderBy?: string;
102
+ orderDir?: "asc" | "desc";
103
+ __orders?: string;
104
+ __keywords?: string | KeywordsSearch;
105
+ __relations?: string[];
106
+ __fields?: string[];
107
+ __filter?: FilterGroup;
108
+ [key: string]: unknown;
109
+ };
110
+ /**
111
+ * Entity list response
112
+ */
113
+ type EntityListResponse<T = Record<string, unknown>> = {
114
+ items: T[];
115
+ total: number;
116
+ page?: number;
117
+ perPage?: number;
118
+ };
119
+
120
+ /**
121
+ * Entity Client - Type-safe client for entity CRUD operations
122
+ *
123
+ * ## Quick Start
124
+ * ```typescript
125
+ * const entityClient = createEntityClient();
126
+ *
127
+ * // List with pagination and sorting
128
+ * const result = await entityClient.list('default', 'tasks', {
129
+ * page: 1,
130
+ * perPage: 20,
131
+ * orderBy: 'createdAt',
132
+ * orderDir: 'desc'
133
+ * });
134
+ *
135
+ * // ⚠️ IMPORTANT: Access items via result.data.items, NOT result.data
136
+ * setTasks(result.data?.items || []); // ✅ Correct
137
+ * setTotal(result.data?.total || 0);
138
+ *
139
+ * // ❌ WRONG: setTasks(result.data || []) - result.data is an object, not an array!
140
+ *
141
+ * // Get single record
142
+ * const task = await entityClient.get('default', 'tasks', 1);
143
+ * setTask(result.data); // ✅ result.data is the entity object directly
144
+ *
145
+ * // CRUD operations
146
+ * await entityClient.create('default', 'tasks', { title: 'New', dueDate: new Date() });
147
+ * await entityClient.update('default', 'tasks', 1, { status: 'done' });
148
+ * await entityClient.delete('default', 'tasks', 1);
149
+ * ```
150
+ *
151
+ * ## Date Handling
152
+ * Date values are automatically converted to backend-compatible format:
153
+ * - Date objects: `new Date()` → `"2026-01-05 10:30:45"`
154
+ * - ISO 8601 strings: `"2026-01-05T00:00:00.000Z"` → `"2026-01-05 00:00:00"`
155
+ * - Works in nested objects and arrays
156
+ *
157
+ * ## Filter Operators
158
+ * eq, ne, gt, ge, lt, le, like, sw, ew, bt, in
159
+ *
160
+ * Usage: `{ 'field[op]': value }` or `{ field: value }` (eq is default)
161
+ */
162
+ type EntityClient = {
163
+ list<T = Record<string, unknown>>(source: string, entity: string, params?: EntityQueryParams): Promise<ClientResult<EntityListResponse<T>>>;
164
+ get<T = Record<string, unknown>>(source: string, entity: string, id: string | number): Promise<ClientResult<T>>;
165
+ create<T = Record<string, unknown>>(source: string, entity: string, data: Record<string, unknown>): Promise<ClientResult<T>>;
166
+ update<T = Record<string, unknown>>(source: string, entity: string, id: string | number, data: Record<string, unknown>): Promise<ClientResult<T>>;
167
+ delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>>;
168
+ options<T = Record<string, unknown>>(source: string, entity: string, fields?: string[]): Promise<ClientResult<T[]>>;
169
+ bulkUpdate<T = Record<string, unknown>>(source: string, entity: string, items: Array<Record<string, unknown> & {
170
+ id: string | number;
171
+ }>): Promise<ClientResult<T>>;
172
+ bulkDelete(source: string, entity: string, ids: Array<string | number>): Promise<ClientResult<null>>;
173
+ };
174
+ declare function createEntityClient(http?: HttpClient): EntityClient;
175
+
176
+ export { type EntityClient, type EntityListResponse, type EntityQueryParams, type FilterGroup, type FilterItem, type FilterOperator, createEntityClient };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import {createHttpClient}from'@amaster.ai/http-client';function c(s){let e;if(s instanceof Date?e=s:typeof s=="string"?e=new Date(s):e=new Date(s),Number.isNaN(e.getTime()))return String(s);let o=e.getUTCFullYear(),r=String(e.getUTCMonth()+1).padStart(2,"0"),n=String(e.getUTCDate()).padStart(2,"0"),t=String(e.getUTCHours()).padStart(2,"0"),i=String(e.getUTCMinutes()).padStart(2,"0"),a=String(e.getUTCSeconds()).padStart(2,"0");return `${o}-${r}-${n} ${t}:${i}:${a}`}function g(s){if(s==null)return s;if(s instanceof Date)return c(s);if(Array.isArray(s))return s.map(e=>g(e));if(typeof s=="object"){let e={};for(let[o,r]of Object.entries(s))e[o]=g(r);return e}return typeof s=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(s)?c(s):s}function u(s,e,o=""){let r=`/api/entity/data/${s}/${e}`;return o?`${r}${o.startsWith("/")?o:`/${o}`}`:r}function d(s){if(!s||Object.keys(s).length===0)return "";let e=new URLSearchParams;for(let[r,n]of Object.entries(s))if(n!=null)if(r==="__filter"&&typeof n=="object")e.append(r,JSON.stringify(n));else if(r==="__relations"&&Array.isArray(n))for(let t of n)e.append("__relations[]",String(t));else if(r==="__fields"&&Array.isArray(n))n.forEach((t,i)=>{e.append(`__fields[${i}]`,String(t));});else if(r==="__keywords"&&typeof n=="object"&&!Array.isArray(n)){let t=n;if(t.fields&&t.fields.length>0&&t.value){let i=t.fields.join(",");e.append(`__keywords[${i}]`,t.value);}}else if(Array.isArray(n))for(let t of n)e.append(r,String(t));else if(typeof n=="object"&&!Array.isArray(n)){for(let[t,i]of Object.entries(n))if(i!=null)if(typeof i=="object"&&!Array.isArray(i))for(let[a,l]of Object.entries(i))l!=null&&e.append(`${r}[${t}][${a}]`,String(l));else Array.isArray(i)?i.forEach((a,l)=>{e.append(`${r}[${t}][${l}]`,String(a));}):e.append(`${r}[${t}]`,String(i));}else e.append(r,String(n));let o=e.toString();return o?`?${o}`:""}function p(s=createHttpClient()){return {async list(e,o,r){let n=u(e,o)+d(r),t=await s.request({url:n,method:"get"});if(t.error||!t.data)return {data:{items:[],total:0},error:t.error,status:t.status};let i=Array.isArray(t.data.items)?t.data.items:[],a=t.data.total??t.data.count??i.length;return {...t,data:{items:i,total:a,page:t.data.page,perPage:t.data.perPage||t.data.pageSize}}},get(e,o,r){if(!r)return Promise.resolve({data:null,error:{message:"Entity ID is required",status:400},status:400});let n=u(e,o,`/${r}`);return s.request({url:n,method:"get"})},create(e,o,r){if(!r||typeof r!="object")return Promise.resolve({data:null,error:{message:"Entity data is required",status:400},status:400});let n=g(r),t=u(e,o);return s.request({url:t,method:"post",headers:{"Content-Type":"application/json"},data:n})},update(e,o,r,n){if(!r)return Promise.resolve({data:null,error:{message:"Entity ID is required",status:400},status:400});if(!n||typeof n!="object")return Promise.resolve({data:null,error:{message:"Entity data is required",status:400},status:400});let t=g(n),i=u(e,o,`/${r}`);return s.request({url:i,method:"put",headers:{"Content-Type":"application/json"},data:t})},async delete(e,o,r){if(!r)return {data:null,error:{message:"Entity ID is required",status:400},status:400};let n=u(e,o,`/${r}`),t=await s.request({url:n,method:"delete"});return t.status===204?{...t,data:null}:t},async options(e,o,r){let n=r&&r.length>0?{"__fields[]":r}:void 0,t=u(e,o,"/options")+d(n),i=await s.request({url:t,method:"get"});return i.error||!i.data?{data:null,error:i.error,status:i.status}:{...i,data:i.data.items||[]}},bulkUpdate(e,o,r){if(!r||r.length===0)return Promise.resolve({data:null,error:{message:"Items array is required",status:400},status:400});let n=r.map(i=>g(i)),t=u(e,o,"/bulkUpdate");return s.request({url:t,method:"post",headers:{"Content-Type":"application/json"},data:{items:n}})},async bulkDelete(e,o,r){if(!r||r.length===0)return {data:null,error:{message:"IDs array is required",status:400},status:400};let n=u(e,o,`/${r.join(",")}`),t=await s.request({url:n,method:"delete"});return t.status===204?{...t,data:null}:t}}}export{p as createEntityClient};//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/entity-client.ts"],"names":["formatDateForBackend","date","dateObj","year","month","day","hours","minutes","seconds","processDataForBackend","data","item","processed","key","value","buildEntityUrl","source","entity","path","basePath","encodeQueryParams","params","searchParams","v","kw","fieldsKey","subKey","subValue","innerKey","innerValue","i","query","createEntityClient","http","createHttpClient","url","result","items","total","id","processedData","fields","processedItems","ids"],"mappings":"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","file":"index.js","sourcesContent":["import { type ClientResult, createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport type { EntityListResponse, EntityQueryParams } from \"./types\";\n\n// Export types for convenience\nexport type {\n AdvancedFilterOperator,\n BetweenValue,\n EntityListResponse,\n EntityQueryParams,\n FilterGroup,\n FilterItem,\n FilterOperator,\n KeywordsSearch,\n} from \"./types\";\n\n/**\n * Entity Client - Type-safe client for entity CRUD operations\n *\n * ## Quick Start\n * ```typescript\n * const entityClient = createEntityClient();\n *\n * // List with pagination and sorting\n * const result = await entityClient.list('default', 'tasks', {\n * page: 1,\n * perPage: 20,\n * orderBy: 'createdAt',\n * orderDir: 'desc'\n * });\n *\n * // ⚠️ IMPORTANT: Access items via result.data.items, NOT result.data\n * setTasks(result.data?.items || []); // ✅ Correct\n * setTotal(result.data?.total || 0);\n *\n * // ❌ WRONG: setTasks(result.data || []) - result.data is an object, not an array!\n *\n * // Get single record\n * const task = await entityClient.get('default', 'tasks', 1);\n * setTask(result.data); // ✅ result.data is the entity object directly\n *\n * // CRUD operations\n * await entityClient.create('default', 'tasks', { title: 'New', dueDate: new Date() });\n * await entityClient.update('default', 'tasks', 1, { status: 'done' });\n * await entityClient.delete('default', 'tasks', 1);\n * ```\n *\n * ## Date Handling\n * Date values are automatically converted to backend-compatible format:\n * - Date objects: `new Date()` → `\"2026-01-05 10:30:45\"`\n * - ISO 8601 strings: `\"2026-01-05T00:00:00.000Z\"` → `\"2026-01-05 00:00:00\"`\n * - Works in nested objects and arrays\n *\n * ## Filter Operators\n * eq, ne, gt, ge, lt, le, like, sw, ew, bt, in\n *\n * Usage: `{ 'field[op]': value }` or `{ field: value }` (eq is default)\n */\nexport type EntityClient = {\n list<T = Record<string, unknown>>(\n source: string,\n entity: string,\n params?: EntityQueryParams\n ): Promise<ClientResult<EntityListResponse<T>>>;\n get<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number\n ): Promise<ClientResult<T>>;\n create<T = Record<string, unknown>>(\n source: string,\n entity: string,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>>;\n update<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>>;\n delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>>;\n options<T = Record<string, unknown>>(\n source: string,\n entity: string,\n fields?: string[]\n ): Promise<ClientResult<T[]>>;\n bulkUpdate<T = Record<string, unknown>>(\n source: string,\n entity: string,\n items: Array<Record<string, unknown> & { id: string | number }>\n ): Promise<ClientResult<T>>;\n bulkDelete(\n source: string,\n entity: string,\n ids: Array<string | number>\n ): Promise<ClientResult<null>>;\n};\n\n// ==================== Helper Functions ====================\n\n/**\n * Convert Date object or ISO 8601 string to backend-compatible DATETIME format\n * Backend expects: \"YYYY-MM-DD HH:MM:SS\" (space-separated, no T or Z)\n */\nfunction formatDateForBackend(date: Date | string): string {\n let dateObj: Date;\n\n if (date instanceof Date) {\n dateObj = date;\n } else if (typeof date === \"string\") {\n dateObj = new Date(date);\n } else {\n dateObj = new Date(date);\n }\n\n // Check if date is valid\n if (Number.isNaN(dateObj.getTime())) {\n return String(date); // Return original value if invalid\n }\n\n // Format as \"YYYY-MM-DD HH:MM:SS\" in UTC\n const year = dateObj.getUTCFullYear();\n const month = String(dateObj.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(dateObj.getUTCDate()).padStart(2, \"0\");\n const hours = String(dateObj.getUTCHours()).padStart(2, \"0\");\n const minutes = String(dateObj.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(dateObj.getUTCSeconds()).padStart(2, \"0\");\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Recursively process data object to convert Date values to backend format\n * Handles nested objects and arrays\n */\nfunction processDataForBackend(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle Date objects\n if (data instanceof Date) {\n return formatDateForBackend(data);\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processDataForBackend(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processDataForBackend(value);\n }\n return processed;\n }\n\n // Handle ISO 8601 date strings (detect pattern)\n if (typeof data === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(data)) {\n return formatDateForBackend(data);\n }\n\n return data;\n}\n\nfunction buildEntityUrl(source: string, entity: string, path = \"\"): string {\n const basePath = `/api/entity/data/${source}/${entity}`;\n return path ? `${basePath}${path.startsWith(\"/\") ? path : `/${path}`}` : basePath;\n}\n\nfunction encodeQueryParams(params?: Record<string, unknown>): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (key === \"__filter\" && typeof value === \"object\") {\n // Advanced filter: JSON stringify\n searchParams.append(key, JSON.stringify(value));\n } else if (key === \"__relations\" && Array.isArray(value)) {\n // Relations: array format\n for (const v of value) {\n searchParams.append(\"__relations[]\", String(v));\n }\n } else if (key === \"__fields\" && Array.isArray(value)) {\n // Fields selection: indexed array format\n value.forEach((v, i) => {\n searchParams.append(`__fields[${i}]`, String(v));\n });\n } else if (key === \"__keywords\" && typeof value === \"object\" && !Array.isArray(value)) {\n // Keywords search with specific fields: __keywords[field1,field2]=value\n const kw = value as { fields?: string[]; value?: string };\n if (kw.fields && kw.fields.length > 0 && kw.value) {\n const fieldsKey = kw.fields.join(\",\");\n searchParams.append(`__keywords[${fieldsKey}]`, kw.value);\n }\n } else if (Array.isArray(value)) {\n // Generic array\n for (const v of value) {\n searchParams.append(key, String(v));\n }\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // Object: nested format (e.g., field[op]=value or field[bt]={from,to})\n for (const [subKey, subValue] of Object.entries(value)) {\n if (subValue !== undefined && subValue !== null) {\n if (typeof subValue === \"object\" && !Array.isArray(subValue)) {\n // Handle nested object like { bt: { from: x, to: y } }\n for (const [innerKey, innerValue] of Object.entries(subValue)) {\n if (innerValue !== undefined && innerValue !== null) {\n searchParams.append(`${key}[${subKey}][${innerKey}]`, String(innerValue));\n }\n }\n } else if (Array.isArray(subValue)) {\n // Handle array in object like { in: [1,2,3] }\n subValue.forEach((v, i) => {\n searchParams.append(`${key}[${subKey}][${i}]`, String(v));\n });\n } else {\n searchParams.append(`${key}[${subKey}]`, String(subValue));\n }\n }\n }\n } else {\n searchParams.append(key, String(value));\n }\n }\n\n const query = searchParams.toString();\n return query ? `?${query}` : \"\";\n}\n\n// ==================== Client Factory ====================\n\nexport function createEntityClient(http: HttpClient = createHttpClient()): EntityClient {\n return {\n async list<T = Record<string, unknown>>(\n source: string,\n entity: string,\n params?: EntityQueryParams\n ): Promise<ClientResult<EntityListResponse<T>>> {\n const url = buildEntityUrl(source, entity) + encodeQueryParams(params);\n const result = await http.request<{\n items: T[];\n count?: number;\n total?: number;\n page?: number;\n perPage?: number;\n pageSize?: number;\n }>({\n url,\n method: \"get\",\n });\n\n if (result.error || !result.data) {\n return {\n data: { items: [], total: 0 },\n error: result.error,\n status: result.status,\n };\n }\n\n const items = Array.isArray(result.data.items) ? result.data.items : [];\n const total = result.data.total ?? result.data.count ?? items.length;\n\n return {\n ...result,\n data: {\n items,\n total,\n page: result.data.page,\n perPage: result.data.perPage || result.data.pageSize,\n },\n };\n },\n\n get<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number\n ): Promise<ClientResult<T>> {\n if (!id) {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n });\n }\n const url = buildEntityUrl(source, entity, `/${id}`);\n return http.request<T>({\n url,\n method: \"get\",\n });\n },\n\n create<T = Record<string, unknown>>(\n source: string,\n entity: string,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>> {\n if (!data || typeof data !== \"object\") {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity data is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedData = processDataForBackend(data);\n\n const url = buildEntityUrl(source, entity);\n return http.request<T>({\n url,\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: processedData,\n });\n },\n\n update<T = Record<string, unknown>>(\n source: string,\n entity: string,\n id: string | number,\n data: Record<string, unknown>\n ): Promise<ClientResult<T>> {\n if (!id) {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n });\n }\n if (!data || typeof data !== \"object\") {\n return Promise.resolve({\n data: null,\n error: { message: \"Entity data is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedData = processDataForBackend(data);\n\n const url = buildEntityUrl(source, entity, `/${id}`);\n return http.request<T>({\n url,\n method: \"put\",\n headers: { \"Content-Type\": \"application/json\" },\n data: processedData,\n });\n },\n\n async delete(source: string, entity: string, id: string | number): Promise<ClientResult<null>> {\n if (!id) {\n return {\n data: null,\n error: { message: \"Entity ID is required\", status: 400 },\n status: 400,\n };\n }\n const url = buildEntityUrl(source, entity, `/${id}`);\n const result = await http.request<null>({\n url,\n method: \"delete\",\n });\n return result.status === 204 ? { ...result, data: null } : result;\n },\n\n async options<T = Record<string, unknown>>(\n source: string,\n entity: string,\n fields?: string[]\n ): Promise<ClientResult<T[]>> {\n const params = fields && fields.length > 0 ? { \"__fields[]\": fields } : undefined;\n\n const url = buildEntityUrl(source, entity, \"/options\") + encodeQueryParams(params);\n const result = await http.request<{ items: T[] }>({\n url,\n method: \"get\",\n });\n\n if (result.error || !result.data) {\n return {\n data: null,\n error: result.error,\n status: result.status,\n };\n }\n\n return {\n ...result,\n data: result.data.items || [],\n };\n },\n\n bulkUpdate<T = Record<string, unknown>>(\n source: string,\n entity: string,\n items: Array<Record<string, unknown> & { id: string | number }>\n ): Promise<ClientResult<T>> {\n if (!items || items.length === 0) {\n return Promise.resolve({\n data: null,\n error: { message: \"Items array is required\", status: 400 },\n status: 400,\n });\n }\n\n const processedItems = items.map((item) => processDataForBackend(item));\n\n const url = buildEntityUrl(source, entity, \"/bulkUpdate\");\n return http.request<T>({\n url,\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { items: processedItems },\n });\n },\n\n async bulkDelete(\n source: string,\n entity: string,\n ids: Array<string | number>\n ): Promise<ClientResult<null>> {\n if (!ids || ids.length === 0) {\n return {\n data: null,\n error: { message: \"IDs array is required\", status: 400 },\n status: 400,\n };\n }\n\n const url = buildEntityUrl(source, entity, `/${ids.join(\",\")}`);\n const result = await http.request<null>({\n url,\n method: \"delete\",\n });\n\n return result.status === 204 ? { ...result, data: null } : result;\n },\n };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@amaster.ai/entity-client",
3
+ "version": "1.0.0-alpha.2",
4
+ "description": "Type-safe CRUD client for entity data management",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "keywords": [
21
+ "entity",
22
+ "crud",
23
+ "api",
24
+ "client",
25
+ "typescript"
26
+ ],
27
+ "author": "Amaster Team",
28
+ "license": "MIT",
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "registry": "https://registry.npmjs.org/"
32
+ },
33
+ "dependencies": {
34
+ "@amaster.ai/http-client": "1.0.0-alpha.2"
35
+ },
36
+ "peerDependencies": {
37
+ "axios": "^1.11.0"
38
+ },
39
+ "devDependencies": {
40
+ "axios": "^1.11.0",
41
+ "tsup": "^8.3.5",
42
+ "typescript": "~5.7.2"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "clean": "rm -rf dist *.tsbuildinfo",
48
+ "type-check": "tsc --noEmit"
49
+ }
50
+ }