@objectstack/client 1.0.4 → 1.0.5

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/query-builder.ts"],"sourcesContent":["import { QueryAST, SortNode, AggregationNode } from '@objectstack/spec/data';\nimport { \n BatchUpdateRequest, \n BatchUpdateResponse, \n UpdateManyRequest,\n DeleteManyRequest,\n BatchOptions,\n MetadataCacheRequest,\n MetadataCacheResponse,\n StandardErrorCode,\n ErrorCategory,\n GetDiscoveryResponse,\n GetMetaTypesResponse,\n GetMetaItemsResponse,\n LoginRequest,\n SessionResponse,\n GetPresignedUrlRequest,\n PresignedUrlResponse,\n CompleteUploadRequest,\n FileUploadResponse\n} from '@objectstack/spec/api';\nimport { Logger, createLogger } from '@objectstack/core';\n\nexport interface ClientConfig {\n baseUrl: string;\n token?: string;\n /**\n * Custom fetch implementation (e.g. node-fetch or for Next.js caching)\n */\n fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n /**\n * Logger instance for debugging\n */\n logger?: Logger;\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n/**\n * Discovery Result\n * Re-export from @objectstack/spec/api for convenience\n */\nexport type DiscoveryResult = GetDiscoveryResponse;\n\nexport interface QueryOptions {\n select?: string[]; // Simplified Selection\n filters?: Record<string, any>; // Map or AST\n sort?: string | string[] | SortNode[]; // 'name' or ['-created_at'] or AST\n top?: number;\n skip?: number;\n // Advanced features\n aggregations?: AggregationNode[];\n groupBy?: string[];\n}\n\nexport interface PaginatedResult<T = any> {\n value: T[];\n count: number;\n}\n\nexport interface StandardError {\n code: StandardErrorCode;\n message: string;\n category: ErrorCategory;\n httpStatus: number;\n retryable: boolean;\n details?: Record<string, any>;\n}\n\nexport class ObjectStackClient {\n private baseUrl: string;\n private token?: string;\n private fetchImpl: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n private discoveryInfo?: DiscoveryResult;\n private logger: Logger;\n\n constructor(config: ClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.token = config.token;\n this.fetchImpl = config.fetch || globalThis.fetch.bind(globalThis);\n \n // Initialize logger\n this.logger = config.logger || createLogger({ \n level: config.debug ? 'debug' : 'info',\n format: 'pretty'\n });\n \n this.logger.debug('ObjectStack client created', { baseUrl: this.baseUrl });\n }\n\n /**\n * Initialize the client by discovering server capabilities.\n */\n async connect() {\n this.logger.debug('Connecting to ObjectStack server', { baseUrl: this.baseUrl });\n \n try {\n // Connect to the discovery endpoint at /api/v1\n const res = await this.fetch(`${this.baseUrl}/api/v1`);\n \n const data = await res.json();\n this.discoveryInfo = data;\n \n this.logger.info('Connected to ObjectStack server', { \n version: data.version,\n apiName: data.apiName,\n capabilities: data.capabilities \n });\n \n return data as DiscoveryResult;\n } catch (e) {\n this.logger.error('Failed to connect to ObjectStack server', e as Error, { baseUrl: this.baseUrl });\n throw e;\n }\n }\n\n /**\n * Metadata Operations\n */\n meta = {\n /**\n * Get all available metadata types\n * Returns types like 'object', 'plugin', 'view', etc.\n */\n getTypes: async (): Promise<GetMetaTypesResponse> => {\n const route = this.getRoute('metadata');\n const res = await this.fetch(`${this.baseUrl}${route}`);\n return res.json();\n },\n\n /**\n * Get all items of a specific metadata type\n * @param type - Metadata type name (e.g., 'object', 'plugin')\n */\n getItems: async (type: string): Promise<GetMetaItemsResponse> => {\n const route = this.getRoute('metadata');\n const res = await this.fetch(`${this.baseUrl}${route}/${type}`);\n return res.json();\n },\n\n /**\n * Get a specific object definition by name\n * @deprecated Use `getItem('object', name)` instead for consistency with spec protocol\n * @param name - Object name (snake_case identifier)\n */\n getObject: async (name: string) => {\n const route = this.getRoute('metadata');\n const res = await this.fetch(`${this.baseUrl}${route}/object/${name}`);\n return res.json();\n },\n\n /**\n * Get a specific metadata item by type and name\n * @param type - Metadata type (e.g., 'object', 'plugin')\n * @param name - Item name (snake_case identifier)\n */\n getItem: async (type: string, name: string) => {\n const route = this.getRoute('metadata');\n const res = await this.fetch(`${this.baseUrl}${route}/${type}/${name}`);\n return res.json();\n },\n\n /**\n * Save a metadata item\n * @param type - Metadata type (e.g., 'object', 'plugin')\n * @param name - Item name\n * @param item - The metadata content to save\n */\n saveItem: async (type: string, name: string, item: any) => {\n const route = this.getRoute('metadata');\n const res = await this.fetch(`${this.baseUrl}${route}/${type}/${name}`, {\n method: 'PUT',\n body: JSON.stringify(item)\n });\n return res.json();\n },\n \n /**\n * Get object metadata with cache support\n * Supports ETag-based conditional requests for efficient caching\n */\n getCached: async (name: string, cacheOptions?: MetadataCacheRequest): Promise<MetadataCacheResponse> => {\n const route = this.getRoute('metadata');\n const headers: Record<string, string> = {};\n \n if (cacheOptions?.ifNoneMatch) {\n headers['If-None-Match'] = cacheOptions.ifNoneMatch;\n }\n if (cacheOptions?.ifModifiedSince) {\n headers['If-Modified-Since'] = cacheOptions.ifModifiedSince;\n }\n \n const res = await this.fetch(`${this.baseUrl}${route}/object/${name}`, {\n headers\n });\n \n // Check for 304 Not Modified\n if (res.status === 304) {\n return {\n notModified: true,\n etag: cacheOptions?.ifNoneMatch ? { \n value: cacheOptions.ifNoneMatch.replace(/^W\\/|\"/g, ''),\n weak: cacheOptions.ifNoneMatch.startsWith('W/')\n } : undefined\n };\n }\n \n const data = await res.json();\n const etag = res.headers.get('ETag');\n const lastModified = res.headers.get('Last-Modified');\n \n return {\n data,\n etag: etag ? { \n value: etag.replace(/^W\\/|\"/g, ''), \n weak: etag.startsWith('W/') \n } : undefined,\n lastModified: lastModified || undefined,\n notModified: false\n };\n },\n \n getView: async (object: string, type: 'list' | 'form' = 'list') => {\n const route = this.getRoute('ui');\n const res = await this.fetch(`${this.baseUrl}${route}/view/${object}?type=${type}`);\n return res.json();\n }\n };\n\n /**\n * Analytics Services\n */\n analytics = {\n query: async (payload: any) => {\n const route = this.getRoute('analytics');\n const res = await this.fetch(`${this.baseUrl}${route}/query`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n return res.json();\n },\n meta: async (cube: string) => {\n const route = this.getRoute('analytics');\n const res = await this.fetch(`${this.baseUrl}${route}/meta/${cube}`);\n return res.json();\n },\n explain: async (payload: any) => {\n const route = this.getRoute('analytics');\n const res = await this.fetch(`${this.baseUrl}${route}/explain`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n return res.json();\n }\n };\n\n /**\n * Hub Management Services\n */\n hub = {\n spaces: {\n list: async () => {\n const route = this.getRoute('hub');\n const res = await this.fetch(`${this.baseUrl}${route}/spaces`);\n return res.json();\n },\n create: async (payload: any) => {\n const route = this.getRoute('hub');\n const res = await this.fetch(`${this.baseUrl}${route}/spaces`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n return res.json();\n }\n },\n plugins: {\n install: async (pkg: string, version?: string) => {\n const route = this.getRoute('hub');\n const res = await this.fetch(`${this.baseUrl}${route}/plugins/install`, {\n method: 'POST',\n body: JSON.stringify({ pkg, version })\n });\n return res.json();\n }\n }\n };\n\n /**\n * Authentication Services\n */\n auth = {\n login: async (request: LoginRequest): Promise<SessionResponse> => {\n const route = this.getRoute('auth');\n const res = await this.fetch(`${this.baseUrl}${route}/login`, {\n method: 'POST',\n body: JSON.stringify(request)\n });\n const data = await res.json();\n // Auto-set token if present in response\n if (data.data?.token) {\n this.token = data.data.token;\n }\n return data;\n },\n \n logout: async () => {\n const route = this.getRoute('auth');\n await this.fetch(`${this.baseUrl}${route}/logout`, { method: 'POST' });\n this.token = undefined;\n },\n\n me: async (): Promise<SessionResponse> => {\n const route = this.getRoute('auth');\n const res = await this.fetch(`${this.baseUrl}${route}/me`);\n return res.json();\n }\n };\n\n /**\n * Storage Services\n */\n storage = {\n upload: async (file: any, scope: string = 'user'): Promise<FileUploadResponse> => {\n // 1. Get Presigned URL\n const presignedReq: GetPresignedUrlRequest = {\n filename: file.name,\n mimeType: file.type,\n size: file.size,\n scope\n };\n \n const route = this.getRoute('storage');\n const presignedRes = await this.fetch(`${this.baseUrl}${route}/upload/presigned`, {\n method: 'POST',\n body: JSON.stringify(presignedReq)\n });\n const { data: presigned } = await presignedRes.json() as { data: PresignedUrlResponse['data'] };\n\n // 2. Upload to Cloud directly (Bypass API Middleware to avoid Auth headers if using S3)\n // Use fetchImpl directly\n const uploadRes = await this.fetchImpl(presigned.uploadUrl, {\n method: presigned.method,\n headers: presigned.headers,\n body: file\n });\n\n if (!uploadRes.ok) {\n throw new Error(`Storage Upload Failed: ${uploadRes.statusText}`);\n }\n\n // 3. Complete Upload\n const completeReq: CompleteUploadRequest = {\n fileId: presigned.fileId\n };\n const completeRes = await this.fetch(`${this.baseUrl}${route}/upload/complete`, {\n method: 'POST',\n body: JSON.stringify(completeReq)\n });\n \n return completeRes.json();\n },\n \n getDownloadUrl: async (fileId: string): Promise<string> => {\n const route = this.getRoute('storage');\n const res = await this.fetch(`${this.baseUrl}${route}/files/${fileId}/url`);\n const data = await res.json();\n return data.url;\n }\n };\n\n /**\n * Automation Services\n */\n automation = {\n trigger: async (triggerName: string, payload: any) => {\n const route = this.getRoute('automation');\n const res = await this.fetch(`${this.baseUrl}${route}/trigger/${triggerName}`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n return res.json();\n }\n };\n\n /**\n * Data Operations\n */\n data = {\n /**\n * Advanced Query using ObjectStack Query Protocol\n * Supports both simplified options and full AST\n */\n query: async <T = any>(object: string, query: Partial<QueryAST>): Promise<PaginatedResult<T>> => {\n const route = this.getRoute('data');\n // POST for complex query to avoid URL length limits and allow clean JSON AST\n // Convention: POST /api/v1/data/:object/query\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/query`, {\n method: 'POST',\n body: JSON.stringify(query)\n });\n return res.json();\n },\n\n find: async <T = any>(object: string, options: QueryOptions = {}): Promise<PaginatedResult<T>> => {\n const route = this.getRoute('data');\n const queryParams = new URLSearchParams();\n \n // 1. Handle Pagination\n if (options.top) queryParams.set('top', options.top.toString());\n if (options.skip) queryParams.set('skip', options.skip.toString());\n\n // 2. Handle Sort\n if (options.sort) {\n // Check if it's AST \n if (Array.isArray(options.sort) && typeof options.sort[0] === 'object') {\n queryParams.set('sort', JSON.stringify(options.sort));\n } else {\n const sortVal = Array.isArray(options.sort) ? options.sort.join(',') : options.sort;\n queryParams.set('sort', sortVal as string);\n }\n }\n \n // 3. Handle Select\n if (options.select) {\n queryParams.set('select', options.select.join(','));\n }\n\n // 4. Handle Filters (Simple vs AST)\n if (options.filters) {\n // If looks like AST (not plain object map)\n // TODO: robust check. safely assuming map for simplified find, and recommending .query() for AST\n if (this.isFilterAST(options.filters)) {\n queryParams.set('filters', JSON.stringify(options.filters));\n } else {\n Object.entries(options.filters).forEach(([k, v]) => {\n if (v !== undefined && v !== null) {\n queryParams.append(k, String(v));\n }\n });\n }\n }\n \n // 5. Handle Aggregations & GroupBy (Pass through as JSON if present)\n if (options.aggregations) {\n queryParams.set('aggregations', JSON.stringify(options.aggregations));\n }\n if (options.groupBy) {\n queryParams.set('groupBy', options.groupBy.join(','));\n }\n\n const res = await this.fetch(`${this.baseUrl}${route}/${object}?${queryParams.toString()}`);\n return res.json();\n },\n\n get: async <T = any>(object: string, id: string): Promise<T> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/${id}`);\n return res.json();\n },\n\n create: async <T = any>(object: string, data: Partial<T>): Promise<T> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}`, {\n method: 'POST',\n body: JSON.stringify(data)\n });\n return res.json();\n },\n\n createMany: async <T = any>(object: string, data: Partial<T>[]): Promise<T[]> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/createMany`, {\n method: 'POST',\n body: JSON.stringify(data)\n });\n return res.json();\n },\n\n update: async <T = any>(object: string, id: string, data: Partial<T>): Promise<T> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/${id}`, {\n method: 'PATCH',\n body: JSON.stringify(data)\n });\n return res.json();\n },\n\n /**\n * Batch update multiple records\n * Uses the new BatchUpdateRequest schema with full control over options\n */\n batch: async (object: string, request: BatchUpdateRequest): Promise<BatchUpdateResponse> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/batch`, {\n method: 'POST',\n body: JSON.stringify(request)\n });\n return res.json();\n },\n\n /**\n * Update multiple records (simplified batch update)\n * Convenience method for batch updates without full BatchUpdateRequest\n */\n updateMany: async <T = any>(\n object: string, \n records: Array<{ id: string; data: Partial<T> }>,\n options?: BatchOptions\n ): Promise<BatchUpdateResponse> => {\n const route = this.getRoute('data');\n const request: UpdateManyRequest = {\n records,\n options\n };\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/updateMany`, {\n method: 'POST',\n body: JSON.stringify(request)\n });\n return res.json();\n },\n\n delete: async (object: string, id: string): Promise<{ success: boolean }> => {\n const route = this.getRoute('data');\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/${id}`, {\n method: 'DELETE'\n });\n return res.json();\n },\n\n /**\n * Delete multiple records by IDs\n */\n deleteMany: async(object: string, ids: string[], options?: BatchOptions): Promise<BatchUpdateResponse> => {\n const route = this.getRoute('data');\n const request: DeleteManyRequest = {\n ids,\n options\n };\n const res = await this.fetch(`${this.baseUrl}${route}/${object}/deleteMany`, {\n method: 'POST',\n body: JSON.stringify(request)\n });\n return res.json();\n }\n };\n\n\n\n /**\n * Private Helpers\n */\n\n private isFilterAST(filter: any): boolean {\n // Basic check: if array, it's [field, op, val] or [logic, node, node]\n // If object but not basic KV map... harder to tell without schema\n // For now, assume if it passes Array.isArray it's an AST root\n return Array.isArray(filter);\n }\n\n private async fetch(url: string, options: RequestInit = {}): Promise<Response> {\n this.logger.debug('HTTP request', { \n method: options.method || 'GET',\n url,\n hasBody: !!options.body\n });\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(options.headers as Record<string, string> || {}),\n };\n\n if (this.token) {\n headers['Authorization'] = `Bearer ${this.token}`;\n }\n\n const res = await this.fetchImpl(url, { ...options, headers });\n \n this.logger.debug('HTTP response', { \n method: options.method || 'GET',\n url,\n status: res.status,\n ok: res.ok\n });\n \n if (!res.ok) {\n let errorBody: any;\n try {\n errorBody = await res.json();\n } catch {\n errorBody = { message: res.statusText };\n }\n \n this.logger.error('HTTP request failed', undefined, { \n method: options.method || 'GET',\n url,\n status: res.status,\n error: errorBody\n });\n \n // Create a standardized error if the response includes error details\n const errorMessage = errorBody?.message || errorBody?.error?.message || res.statusText;\n const errorCode = errorBody?.code || errorBody?.error?.code;\n const error = new Error(`[ObjectStack] ${errorCode ? `${errorCode}: ` : ''}${errorMessage}`) as any;\n \n // Attach error details for programmatic access\n error.code = errorCode;\n error.category = errorBody?.category;\n error.httpStatus = res.status;\n error.retryable = errorBody?.retryable;\n error.details = errorBody?.details || errorBody;\n \n throw error;\n }\n \n return res;\n }\n\n /**\n * Get the conventional route path for a given API endpoint type\n * ObjectStack uses standard conventions: /api/v1/data, /api/v1/metadata, /api/v1/ui\n */\n private getRoute(type: 'data' | 'metadata' | 'ui' | 'auth' | 'analytics' | 'hub' | 'storage' | 'automation'): string {\n // 1. Use discovered routes if available\n // Note: Spec uses 'endpoints', mapped dynamically\n if (this.discoveryInfo?.endpoints && (this.discoveryInfo.endpoints as any)[type]) {\n return (this.discoveryInfo.endpoints as any)[type];\n }\n\n // 2. Fallback to conventions\n // Note: HttpDispatcher expects /metadata, not /meta\n const routeMap: Record<string, string> = {\n data: '/api/v1/data',\n metadata: '/api/v1/metadata',\n ui: '/api/v1/ui',\n auth: '/api/v1/auth',\n analytics: '/api/v1/analytics',\n hub: '/api/v1/hub',\n storage: '/api/v1/storage',\n automation: '/api/v1/automation'\n };\n \n return routeMap[type] || `/api/v1/${type}`;\n }\n}\n\n// Re-export type-safe query builder\nexport { QueryBuilder, FilterBuilder, createQuery, createFilter } from './query-builder';\n\n// Re-export commonly used types from @objectstack/spec/api for convenience\nexport type {\n BatchUpdateRequest,\n BatchUpdateResponse,\n UpdateManyRequest,\n DeleteManyRequest,\n BatchOptions,\n BatchRecord,\n BatchOperationResult,\n MetadataCacheRequest,\n MetadataCacheResponse,\n StandardErrorCode,\n ErrorCategory,\n GetDiscoveryResponse,\n GetMetaTypesResponse,\n GetMetaItemsResponse\n} from '@objectstack/spec/api';\n","/**\n * Type-Safe Query Builder\n * \n * Provides a fluent API for building ObjectStack queries with:\n * - Compile-time type checking\n * - Intelligent code completion\n * - Runtime validation\n * - Type-safe filters and selections\n */\n\nimport { QueryAST, FilterCondition, SortNode } from '@objectstack/spec/data';\n\n/**\n * Type-safe filter builder\n */\nexport class FilterBuilder<T = any> {\n private conditions: FilterCondition[] = [];\n\n /**\n * Equality filter: field = value\n */\n equals<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '=', value]);\n return this;\n }\n\n /**\n * Not equals filter: field != value\n */\n notEquals<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '!=', value]);\n return this;\n }\n\n /**\n * Greater than filter: field > value\n */\n greaterThan<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '>', value]);\n return this;\n }\n\n /**\n * Greater than or equal filter: field >= value\n */\n greaterThanOrEqual<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '>=', value]);\n return this;\n }\n\n /**\n * Less than filter: field < value\n */\n lessThan<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '<', value]);\n return this;\n }\n\n /**\n * Less than or equal filter: field <= value\n */\n lessThanOrEqual<K extends keyof T>(field: K, value: T[K]): this {\n this.conditions.push([field as string, '<=', value]);\n return this;\n }\n\n /**\n * IN filter: field IN (value1, value2, ...)\n */\n in<K extends keyof T>(field: K, values: T[K][]): this {\n this.conditions.push([field as string, 'in', values]);\n return this;\n }\n\n /**\n * NOT IN filter: field NOT IN (value1, value2, ...)\n */\n notIn<K extends keyof T>(field: K, values: T[K][]): this {\n this.conditions.push([field as string, 'not_in', values]);\n return this;\n }\n\n /**\n * LIKE filter: field LIKE pattern\n */\n like<K extends keyof T>(field: K, pattern: string): this {\n this.conditions.push([field as string, 'like', pattern]);\n return this;\n }\n\n /**\n * IS NULL filter: field IS NULL\n */\n isNull<K extends keyof T>(field: K): this {\n this.conditions.push([field as string, 'is_null', null]);\n return this;\n }\n\n /**\n * IS NOT NULL filter: field IS NOT NULL\n */\n isNotNull<K extends keyof T>(field: K): this {\n this.conditions.push([field as string, 'is_not_null', null]);\n return this;\n }\n\n /**\n * Build the filter condition\n */\n build(): FilterCondition {\n if (this.conditions.length === 0) {\n throw new Error('Filter builder has no conditions');\n }\n if (this.conditions.length === 1) {\n return this.conditions[0];\n }\n // Combine multiple conditions with AND\n return ['and', ...this.conditions];\n }\n\n /**\n * Get raw conditions array\n */\n getConditions(): FilterCondition[] {\n return this.conditions;\n }\n}\n\n/**\n * Type-safe query builder\n */\nexport class QueryBuilder<T = any> {\n private query: Partial<QueryAST> = {};\n private _object: string;\n\n constructor(object: string) {\n this._object = object;\n this.query.object = object;\n }\n\n /**\n * Select specific fields\n */\n select<K extends keyof T>(...fields: K[]): this {\n this.query.fields = fields as string[];\n return this;\n }\n\n /**\n * Add filters using a builder function\n */\n where(builderFn: (builder: FilterBuilder<T>) => void): this {\n const builder = new FilterBuilder<T>();\n builderFn(builder);\n const conditions = builder.getConditions();\n \n if (conditions.length === 1) {\n this.query.where = conditions[0];\n } else if (conditions.length > 1) {\n this.query.where = ['and', ...conditions] as FilterCondition;\n }\n \n return this;\n }\n\n /**\n * Add raw filter condition\n */\n filter(condition: FilterCondition): this {\n this.query.where = condition;\n return this;\n }\n\n /**\n * Sort by fields\n */\n orderBy<K extends keyof T>(field: K, order: 'asc' | 'desc' = 'asc'): this {\n if (!this.query.orderBy) {\n this.query.orderBy = [];\n }\n (this.query.orderBy as SortNode[]).push({\n field: field as string,\n order\n });\n return this;\n }\n\n /**\n * Limit the number of results\n */\n limit(count: number): this {\n this.query.limit = count;\n return this;\n }\n\n /**\n * Skip records (for pagination)\n */\n skip(count: number): this {\n this.query.offset = count;\n return this;\n }\n\n /**\n * Paginate results\n */\n paginate(page: number, pageSize: number): this {\n this.query.limit = pageSize;\n this.query.offset = (page - 1) * pageSize;\n return this;\n }\n\n /**\n * Group by fields\n */\n groupBy<K extends keyof T>(...fields: K[]): this {\n this.query.groupBy = fields as string[];\n return this;\n }\n\n /**\n * Build the final query AST\n */\n build(): QueryAST {\n return {\n object: this._object,\n ...this.query\n } as QueryAST;\n }\n\n /**\n * Get the current query state\n */\n getQuery(): Partial<QueryAST> {\n return { ...this.query };\n }\n}\n\n/**\n * Create a type-safe query builder for an object\n */\nexport function createQuery<T = any>(object: string): QueryBuilder<T> {\n return new QueryBuilder<T>(object);\n}\n\n/**\n * Create a type-safe filter builder\n */\nexport function createFilter<T = any>(): FilterBuilder<T> {\n return new FilterBuilder<T>();\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@objectstack/client",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Official Client SDK for ObjectStack Protocol",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "dependencies": {
9
- "@objectstack/spec": "1.0.4",
10
- "@objectstack/core": "1.0.4"
9
+ "@objectstack/spec": "1.0.5",
10
+ "@objectstack/core": "1.0.5"
11
11
  },
12
12
  "devDependencies": {
13
13
  "typescript": "^5.0.0",
14
14
  "vitest": "^4.0.18"
15
15
  },
16
16
  "scripts": {
17
- "build": "tsc",
17
+ "build": "tsup --config ../../tsup.config.ts",
18
18
  "test": "vitest run"
19
19
  }
20
20
  }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { QueryAST, SortNode, AggregationNode, WindowFunctionNode } from '@objectstack/spec/data';
1
+ import { QueryAST, SortNode, AggregationNode } from '@objectstack/spec/data';
2
2
  import {
3
3
  BatchUpdateRequest,
4
4
  BatchUpdateResponse,
package/tsconfig.json CHANGED
@@ -1,13 +1,9 @@
1
1
  {
2
+ "extends": "../../tsconfig.json",
2
3
  "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ES2020",
5
- "moduleResolution": "bundler",
6
- "declaration": true,
7
4
  "outDir": "./dist",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true
5
+ "rootDir": "./src",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"]
11
7
  },
12
8
  "include": ["src/**/*"],
13
9
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
@@ -1,124 +0,0 @@
1
- /**
2
- * Type-Safe Query Builder
3
- *
4
- * Provides a fluent API for building ObjectStack queries with:
5
- * - Compile-time type checking
6
- * - Intelligent code completion
7
- * - Runtime validation
8
- * - Type-safe filters and selections
9
- */
10
- import { QueryAST, FilterCondition } from '@objectstack/spec/data';
11
- /**
12
- * Type-safe filter builder
13
- */
14
- export declare class FilterBuilder<T = any> {
15
- private conditions;
16
- /**
17
- * Equality filter: field = value
18
- */
19
- equals<K extends keyof T>(field: K, value: T[K]): this;
20
- /**
21
- * Not equals filter: field != value
22
- */
23
- notEquals<K extends keyof T>(field: K, value: T[K]): this;
24
- /**
25
- * Greater than filter: field > value
26
- */
27
- greaterThan<K extends keyof T>(field: K, value: T[K]): this;
28
- /**
29
- * Greater than or equal filter: field >= value
30
- */
31
- greaterThanOrEqual<K extends keyof T>(field: K, value: T[K]): this;
32
- /**
33
- * Less than filter: field < value
34
- */
35
- lessThan<K extends keyof T>(field: K, value: T[K]): this;
36
- /**
37
- * Less than or equal filter: field <= value
38
- */
39
- lessThanOrEqual<K extends keyof T>(field: K, value: T[K]): this;
40
- /**
41
- * IN filter: field IN (value1, value2, ...)
42
- */
43
- in<K extends keyof T>(field: K, values: T[K][]): this;
44
- /**
45
- * NOT IN filter: field NOT IN (value1, value2, ...)
46
- */
47
- notIn<K extends keyof T>(field: K, values: T[K][]): this;
48
- /**
49
- * LIKE filter: field LIKE pattern
50
- */
51
- like<K extends keyof T>(field: K, pattern: string): this;
52
- /**
53
- * IS NULL filter: field IS NULL
54
- */
55
- isNull<K extends keyof T>(field: K): this;
56
- /**
57
- * IS NOT NULL filter: field IS NOT NULL
58
- */
59
- isNotNull<K extends keyof T>(field: K): this;
60
- /**
61
- * Build the filter condition
62
- */
63
- build(): FilterCondition;
64
- /**
65
- * Get raw conditions array
66
- */
67
- getConditions(): FilterCondition[];
68
- }
69
- /**
70
- * Type-safe query builder
71
- */
72
- export declare class QueryBuilder<T = any> {
73
- private query;
74
- private _object;
75
- constructor(object: string);
76
- /**
77
- * Select specific fields
78
- */
79
- select<K extends keyof T>(...fields: K[]): this;
80
- /**
81
- * Add filters using a builder function
82
- */
83
- where(builderFn: (builder: FilterBuilder<T>) => void): this;
84
- /**
85
- * Add raw filter condition
86
- */
87
- filter(condition: FilterCondition): this;
88
- /**
89
- * Sort by fields
90
- */
91
- orderBy<K extends keyof T>(field: K, order?: 'asc' | 'desc'): this;
92
- /**
93
- * Limit the number of results
94
- */
95
- limit(count: number): this;
96
- /**
97
- * Skip records (for pagination)
98
- */
99
- skip(count: number): this;
100
- /**
101
- * Paginate results
102
- */
103
- paginate(page: number, pageSize: number): this;
104
- /**
105
- * Group by fields
106
- */
107
- groupBy<K extends keyof T>(...fields: K[]): this;
108
- /**
109
- * Build the final query AST
110
- */
111
- build(): QueryAST;
112
- /**
113
- * Get the current query state
114
- */
115
- getQuery(): Partial<QueryAST>;
116
- }
117
- /**
118
- * Create a type-safe query builder for an object
119
- */
120
- export declare function createQuery<T = any>(object: string): QueryBuilder<T>;
121
- /**
122
- * Create a type-safe filter builder
123
- */
124
- export declare function createFilter<T = any>(): FilterBuilder<T>;
@@ -1,221 +0,0 @@
1
- /**
2
- * Type-Safe Query Builder
3
- *
4
- * Provides a fluent API for building ObjectStack queries with:
5
- * - Compile-time type checking
6
- * - Intelligent code completion
7
- * - Runtime validation
8
- * - Type-safe filters and selections
9
- */
10
- /**
11
- * Type-safe filter builder
12
- */
13
- export class FilterBuilder {
14
- constructor() {
15
- this.conditions = [];
16
- }
17
- /**
18
- * Equality filter: field = value
19
- */
20
- equals(field, value) {
21
- this.conditions.push([field, '=', value]);
22
- return this;
23
- }
24
- /**
25
- * Not equals filter: field != value
26
- */
27
- notEquals(field, value) {
28
- this.conditions.push([field, '!=', value]);
29
- return this;
30
- }
31
- /**
32
- * Greater than filter: field > value
33
- */
34
- greaterThan(field, value) {
35
- this.conditions.push([field, '>', value]);
36
- return this;
37
- }
38
- /**
39
- * Greater than or equal filter: field >= value
40
- */
41
- greaterThanOrEqual(field, value) {
42
- this.conditions.push([field, '>=', value]);
43
- return this;
44
- }
45
- /**
46
- * Less than filter: field < value
47
- */
48
- lessThan(field, value) {
49
- this.conditions.push([field, '<', value]);
50
- return this;
51
- }
52
- /**
53
- * Less than or equal filter: field <= value
54
- */
55
- lessThanOrEqual(field, value) {
56
- this.conditions.push([field, '<=', value]);
57
- return this;
58
- }
59
- /**
60
- * IN filter: field IN (value1, value2, ...)
61
- */
62
- in(field, values) {
63
- this.conditions.push([field, 'in', values]);
64
- return this;
65
- }
66
- /**
67
- * NOT IN filter: field NOT IN (value1, value2, ...)
68
- */
69
- notIn(field, values) {
70
- this.conditions.push([field, 'not_in', values]);
71
- return this;
72
- }
73
- /**
74
- * LIKE filter: field LIKE pattern
75
- */
76
- like(field, pattern) {
77
- this.conditions.push([field, 'like', pattern]);
78
- return this;
79
- }
80
- /**
81
- * IS NULL filter: field IS NULL
82
- */
83
- isNull(field) {
84
- this.conditions.push([field, 'is_null', null]);
85
- return this;
86
- }
87
- /**
88
- * IS NOT NULL filter: field IS NOT NULL
89
- */
90
- isNotNull(field) {
91
- this.conditions.push([field, 'is_not_null', null]);
92
- return this;
93
- }
94
- /**
95
- * Build the filter condition
96
- */
97
- build() {
98
- if (this.conditions.length === 0) {
99
- throw new Error('Filter builder has no conditions');
100
- }
101
- if (this.conditions.length === 1) {
102
- return this.conditions[0];
103
- }
104
- // Combine multiple conditions with AND
105
- return ['and', ...this.conditions];
106
- }
107
- /**
108
- * Get raw conditions array
109
- */
110
- getConditions() {
111
- return this.conditions;
112
- }
113
- }
114
- /**
115
- * Type-safe query builder
116
- */
117
- export class QueryBuilder {
118
- constructor(object) {
119
- this.query = {};
120
- this._object = object;
121
- this.query.object = object;
122
- }
123
- /**
124
- * Select specific fields
125
- */
126
- select(...fields) {
127
- this.query.fields = fields;
128
- return this;
129
- }
130
- /**
131
- * Add filters using a builder function
132
- */
133
- where(builderFn) {
134
- const builder = new FilterBuilder();
135
- builderFn(builder);
136
- const conditions = builder.getConditions();
137
- if (conditions.length === 1) {
138
- this.query.where = conditions[0];
139
- }
140
- else if (conditions.length > 1) {
141
- this.query.where = ['and', ...conditions];
142
- }
143
- return this;
144
- }
145
- /**
146
- * Add raw filter condition
147
- */
148
- filter(condition) {
149
- this.query.where = condition;
150
- return this;
151
- }
152
- /**
153
- * Sort by fields
154
- */
155
- orderBy(field, order = 'asc') {
156
- if (!this.query.orderBy) {
157
- this.query.orderBy = [];
158
- }
159
- this.query.orderBy.push({
160
- field: field,
161
- order
162
- });
163
- return this;
164
- }
165
- /**
166
- * Limit the number of results
167
- */
168
- limit(count) {
169
- this.query.limit = count;
170
- return this;
171
- }
172
- /**
173
- * Skip records (for pagination)
174
- */
175
- skip(count) {
176
- this.query.offset = count;
177
- return this;
178
- }
179
- /**
180
- * Paginate results
181
- */
182
- paginate(page, pageSize) {
183
- this.query.limit = pageSize;
184
- this.query.offset = (page - 1) * pageSize;
185
- return this;
186
- }
187
- /**
188
- * Group by fields
189
- */
190
- groupBy(...fields) {
191
- this.query.groupBy = fields;
192
- return this;
193
- }
194
- /**
195
- * Build the final query AST
196
- */
197
- build() {
198
- return {
199
- object: this._object,
200
- ...this.query
201
- };
202
- }
203
- /**
204
- * Get the current query state
205
- */
206
- getQuery() {
207
- return { ...this.query };
208
- }
209
- }
210
- /**
211
- * Create a type-safe query builder for an object
212
- */
213
- export function createQuery(object) {
214
- return new QueryBuilder(object);
215
- }
216
- /**
217
- * Create a type-safe filter builder
218
- */
219
- export function createFilter() {
220
- return new FilterBuilder();
221
- }