diff --git a/docs/community/architecture/specs/base-components.md b/docs/community/architecture/specs/base-components.md index 9737ff8..75fb209 100644 --- a/docs/community/architecture/specs/base-components.md +++ b/docs/community/architecture/specs/base-components.md @@ -367,11 +367,11 @@ dependencies: version: "^18.0.0" type: peer - - name: "@objectql/core" + - name: "@objectstack/client" version: "^1.7.0" type: library - - name: "@objectql/types" + - name: "@objectstack/spec" version: "^1.7.0" type: library diff --git a/docs/community/architecture/specs/component-package.md b/docs/community/architecture/specs/component-package.md index 454294c..1e70f27 100644 --- a/docs/community/architecture/specs/component-package.md +++ b/docs/community/architecture/specs/component-package.md @@ -102,7 +102,7 @@ Every component package must include an `objectql.package.json` file: }, "peerDependencies": { - "@objectql/types": "^1.7.0", + "@objectstack/spec": "^1.7.0", "tailwindcss": "^3.0.0" }, @@ -149,7 +149,7 @@ Standard npm package.json with UMD build configuration: "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", - "@objectql/types": "^1.7.0" + "@objectstack/spec": "^1.7.0" }, "devDependencies": { @@ -191,7 +191,7 @@ export default { globals: { 'react': 'React', 'react-dom': 'ReactDOM', - '@objectql/types': 'ObjectQLTypes' + '@objectstack/spec': 'ObjectQLTypes' }, sourcemap: true }, @@ -202,7 +202,7 @@ export default { } ], - external: ['react', 'react-dom', '@objectql/types'], + external: ['react', 'react-dom', '@objectstack/spec'], plugins: [ resolve(), @@ -246,7 +246,7 @@ export const OBJECTQL_VERSION = '^1.7.0'; ```typescript import React from 'react'; -import type { ComponentProps } from '@objectql/types'; +import type { ComponentProps } from '@objectstack/spec'; export interface MyTableProps extends ComponentProps { object: string; @@ -327,7 +327,7 @@ dependencies: version: "^18.0.0" type: library - - name: "@objectql/types" + - name: "@objectstack/spec" version: "^1.7.0" type: library diff --git a/docs/community/architecture/specs/component.md b/docs/community/architecture/specs/component.md index 82968f7..d35694a 100644 --- a/docs/community/architecture/specs/component.md +++ b/docs/community/architecture/specs/component.md @@ -504,7 +504,7 @@ license: MIT Components are automatically registered when ObjectQL scans your directories: ```typescript -import { ObjectQL } from '@objectql/core'; +import { ObjectQL } from '@objectstack/client'; const app = new ObjectQL({ source: './src', @@ -529,7 +529,7 @@ const tableComponent = app.registry.get('component', 'ObjectTable'); Register components programmatically: ```typescript -import { ComponentConfig } from '@objectql/types'; +import { ComponentConfig } from '@objectstack/spec'; const customTable: ComponentConfig = { name: 'custom_table', @@ -578,7 +578,7 @@ Generate TypeScript types from component metadata: ```typescript // Auto-generated types from component metadata -import type { ObjectTableProps } from '@objectql/types/components'; +import type { ObjectTableProps } from '@objectstack/spec/components'; const props: ObjectTableProps = { object: 'projects', @@ -595,7 +595,7 @@ const props: ObjectTableProps = { Test components using ObjectQL's testing utilities: ```typescript -import { renderComponent } from '@objectql/test-utils'; +import { renderComponent } from '@objectstack/spec'; describe('CustomTable', () => { it('renders with data', async () => { diff --git a/docs/reference/protocol/form.md b/docs/reference/protocol/form.md index 2ea6857..69e8a0f 100644 --- a/docs/reference/protocol/form.md +++ b/docs/reference/protocol/form.md @@ -1028,7 +1028,7 @@ modes: ```typescript // src/forms/project.form.yml -import { FormDefinition } from '@objectql/types'; +import { FormDefinition } from '@objectstack/spec'; export const project_form: FormDefinition = { name: 'project_form', diff --git a/docs/reference/protocol/menu.md b/docs/reference/protocol/menu.md index bdbe09f..d587815 100644 --- a/docs/reference/protocol/menu.md +++ b/docs/reference/protocol/menu.md @@ -726,7 +726,7 @@ items: ```typescript // File: main_navigation.menu.ts -import { MenuDefinition } from '@objectql/types'; +import { MenuDefinition } from '@objectstack/spec'; export const main_menu: MenuDefinition = { type: 'sidebar', diff --git a/docs/reference/protocol/report.md b/docs/reference/protocol/report.md index 271db3d..924867b 100644 --- a/docs/reference/protocol/report.md +++ b/docs/reference/protocol/report.md @@ -751,7 +751,7 @@ permissions: ```typescript // src/reports/sales_summary.report.yml -import { ReportDefinition } from '@objectql/types'; +import { ReportDefinition } from '@objectstack/spec'; export const sales_summary: ReportDefinition = { name: 'sales_summary', diff --git a/docs/reference/protocol/view.md b/docs/reference/protocol/view.md index 94c57e5..6bce567 100644 --- a/docs/reference/protocol/view.md +++ b/docs/reference/protocol/view.md @@ -399,7 +399,7 @@ permissions: ```typescript // src/views/task_list.view.yml -import { ViewDefinition } from '@objectql/types'; +import { ViewDefinition } from '@objectstack/spec'; export const task_list: ViewDefinition = { name: 'task_list', diff --git a/packages/data-objectql/README.md b/packages/data-objectql/README.md index d2cbdc3..c4764e9 100644 --- a/packages/data-objectql/README.md +++ b/packages/data-objectql/README.md @@ -1,14 +1,14 @@ # @object-ui/data-objectql -ObjectQL Data Source Adapter for Object UI - Seamlessly connect your Object UI components with ObjectQL API backends using the official **@objectql/sdk**. +ObjectQL Data Source Adapter for Object UI - Seamlessly connect your Object UI components with ObjectQL API backends using the official **@objectstack/client**. ## Features -- ✅ **Official SDK Integration** - Built on top of @objectql/sdk for reliable API communication +- ✅ **Official SDK Integration** - Built on top of @objectstack/client for reliable API communication - ✅ **Universal DataSource Interface** - Implements the standard Object UI data source protocol - ✅ **Full TypeScript Support** - Complete type definitions and IntelliSense - ✅ **React Hooks** - Easy-to-use hooks for data fetching and mutations -- ✅ **Automatic Query Conversion** - Converts universal query params to ObjectQL format +- ✅ **Automatic Query Conversion** - Converts universal query params to ObjectStack format - ✅ **Error Handling** - Robust error handling with typed error responses - ✅ **Authentication** - Built-in support for token-based authentication - ✅ **Universal Runtime** - Works in browsers, Node.js, and edge runtimes @@ -17,16 +17,16 @@ ObjectQL Data Source Adapter for Object UI - Seamlessly connect your Object UI c ```bash # Using npm -npm install @object-ui/data-objectql @objectql/sdk +npm install @object-ui/data-objectql @objectstack/client # Using yarn -yarn add @object-ui/data-objectql @objectql/sdk +yarn add @object-ui/data-objectql @objectstack/client # Using pnpm -pnpm add @object-ui/data-objectql @objectql/sdk +pnpm add @object-ui/data-objectql @objectstack/client ``` -**Note**: The package now depends on `@objectql/sdk` and `@objectql/types`, which provide the underlying HTTP client and type definitions. +**Note**: The package now depends on `@objectstack/client`, which provides the underlying HTTP client and ObjectStack Protocol support. ## Quick Start @@ -147,13 +147,10 @@ new ObjectQLDataSource(config: ObjectQLConfig) ```typescript interface ObjectQLConfig { baseUrl: string; // ObjectQL API base URL - token?: string; // Authentication token - headers?: Record; // Additional headers - timeout?: number; // Request timeout (default: 30000ms) } ``` -**Note**: This configuration is compatible with `@objectql/sdk`'s `DataApiClientConfig`. Additional options supported by the SDK can also be passed. +**Note**: This configuration is compatible with `@objectstack/client`'s `ClientConfig`. Additional options supported by the SDK can also be passed. #### Methods @@ -382,47 +379,49 @@ const contact: Contact = result.data[0]; // Typed! ## Architecture -This adapter is built on top of the official ObjectQL SDK: +This adapter is built on top of the official ObjectStack client: ``` Object UI Components ↓ @object-ui/data-objectql (this package) ↓ -@objectql/sdk (DataApiClient) +@objectstack/client (ObjectStackClient) ↓ -ObjectQL Server API +ObjectStack Protocol Server API ``` ### Benefits of Using the Official SDK -- **Reliability**: Uses the official, well-tested ObjectQL HTTP client -- **Compatibility**: Always compatible with the latest ObjectQL server versions -- **Type Safety**: Leverages @objectql/types for consistent type definitions +- **Reliability**: Uses the official, well-tested ObjectStack HTTP client +- **Compatibility**: Always compatible with the latest ObjectStack Protocol server versions +- **Type Safety**: Leverages @objectstack/spec for consistent type definitions - **Universal Runtime**: Works in browsers, Node.js, Deno, and edge runtimes - **Automatic Updates**: SDK improvements automatically benefit this adapter ## Migration from Previous Versions -If you're upgrading from a previous version that used custom fetch logic: +If you're upgrading from a previous version that used `@objectql/sdk`: -1. Update your dependencies to include `@objectql/sdk`: +1. Update your dependencies to use `@objectstack/client`: ```bash - pnpm add @objectql/sdk @objectql/types + pnpm remove @objectql/sdk @objectql/types + pnpm add @objectstack/client ``` -2. The configuration interface has been simplified. Remove deprecated options: - - `version` - The SDK handles API versioning internally - - `spaceId` - Use custom headers if needed - - `withCredentials` - The SDK manages this automatically +2. The configuration interface remains compatible - no code changes required! + The adapter now uses the ObjectStack Protocol client under the hood. -3. Filter formats now support both object and array notation: +3. Filter formats support the standard ObjectStack query format: ```typescript - // Object format (converted to array internally) + // Object format (converted to ObjectStack query internally) $filter: { status: 'active', age: 18 } - // Array format (FilterExpression - native ObjectQL format) - $filter: [['status', '=', 'active'], ['age', '=', 18]] + // Complex filters with operators + $filter: { + age: { $gte: 18, $lte: 65 }, + status: { $in: ['active', 'pending'] } + } ``` ## License @@ -433,5 +432,5 @@ MIT - [Object UI Documentation](https://www.objectui.org) - [GitHub Repository](https://github.com/objectstack-ai/objectui) -- [ObjectQL Documentation](https://www.objectql.com) -- [ObjectQL SDK](https://github.com/objectstack-ai/objectql) +- [ObjectStack Protocol](https://github.com/objectstack-ai/spec) +- [ObjectStack Client](https://github.com/objectstack-ai/client) diff --git a/packages/data-objectql/package.json b/packages/data-objectql/package.json index 45ff697..17755c9 100644 --- a/packages/data-objectql/package.json +++ b/packages/data-objectql/package.json @@ -44,16 +44,9 @@ ], "author": "Object UI Team", "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/objectstack-ai/objectui.git", - "directory": "packages/data-objectql" - }, "dependencies": { "@object-ui/types": "workspace:*", - "@objectstack/client": "^0.1.1", - "@objectql/sdk": "^3.0.1", - "@objectql/types": "^3.0.1" + "@objectstack/client": "^0.1.1" }, "devDependencies": { "typescript": "^5.9.3", diff --git a/packages/data-objectql/src/ObjectQLDataSource.ts b/packages/data-objectql/src/ObjectQLDataSource.ts index 3febb8d..373ff38 100644 --- a/packages/data-objectql/src/ObjectQLDataSource.ts +++ b/packages/data-objectql/src/ObjectQLDataSource.ts @@ -13,7 +13,7 @@ * with ObjectQL API backends. It implements the universal DataSource interface * from @object-ui/types to provide seamless data access. * - * This adapter uses the official @objectql/sdk package for all API communication. + * This adapter uses the official @objectstack/client package for all API communication. * * @module data-objectql * @packageDocumentation @@ -26,12 +26,11 @@ import type { APIError } from '@object-ui/types'; -import { DataApiClient, MetadataApiClient } from '@objectql/sdk'; +import { ObjectStackClient } from '@objectstack/client'; import type { - DataApiClientConfig, - DataApiListParams, - FilterExpression -} from '@objectql/types'; + ClientConfig, + QueryOptions +} from '@objectstack/client'; /** * ObjectQL-specific query parameters. @@ -50,7 +49,7 @@ export interface ObjectQLQueryParams extends QueryParams { * @example { name: 'John', age: { $gte: 18 } } * @example [['name', '=', 'John'], ['age', '>=', 18]] */ - filters?: FilterExpression; + filters?: Record; /** * Sort configuration @@ -76,9 +75,9 @@ export interface ObjectQLQueryParams extends QueryParams { /** * ObjectQL connection configuration - * Compatible with @objectql/sdk DataApiClientConfig + * Compatible with @objectstack/client ClientConfig */ -export interface ObjectQLConfig extends DataApiClientConfig { +export interface ObjectQLConfig extends ClientConfig { /** * Base URL of the ObjectQL server * @example 'https://api.example.com' or '/api' @@ -92,22 +91,16 @@ export interface ObjectQLConfig extends DataApiClientConfig { token?: string; /** - * Additional headers to include in requests + * Custom fetch implementation (optional) */ - headers?: Record; - - /** - * Request timeout in milliseconds - * @default 30000 - */ - timeout?: number; + fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise; } /** * ObjectQL Data Source Adapter * * Implements the universal DataSource interface to connect Object UI - * components with ObjectQL API backends using the official @objectql/sdk. + * components with ObjectQL API backends using the official @objectstack/client. * * @template T - The data type * @@ -138,95 +131,52 @@ export interface ObjectQLConfig extends DataApiClientConfig { * ``` */ export class ObjectQLDataSource implements DataSource { - private client: DataApiClient; - private metadataClient: MetadataApiClient; + private client: ObjectStackClient; constructor(config: ObjectQLConfig) { - // Initialize the official ObjectQL SDK client - this.client = new DataApiClient(config); - this.metadataClient = new MetadataApiClient(config); + // Initialize the official ObjectStack client + this.client = new ObjectStackClient(config); } /** - * Convert universal QueryParams to ObjectQL DataApiListParams format + * Convert universal QueryParams to ObjectStack QueryOptions format */ - private convertParams(params?: QueryParams): DataApiListParams { + private convertParams(params?: QueryParams): QueryOptions { if (!params) return {}; - const objectqlParams: DataApiListParams = {}; + const queryOptions: QueryOptions = {}; - // Convert $select to fields + // Convert $select to select (field list) if (params.$select) { - objectqlParams.fields = params.$select; + queryOptions.select = params.$select; } - // Convert $filter to filters (FilterExpression format) + // Convert $filter to filters if (params.$filter) { - // If it's already an array (FilterExpression), use it directly - if (Array.isArray(params.$filter)) { - objectqlParams.filter = params.$filter as FilterExpression; - } else { - // Convert object format (including Mongo-like operator objects) to FilterExpression format - const filterEntries = Object.entries(params.$filter); - const filters: any[] = []; - - const operatorMap: Record = { - $eq: '=', - $ne: '!=', - $gt: '>', - $gte: '>=', - $lt: '<', - $lte: '<=', - $in: 'in', - $nin: 'not-in', - }; - - for (const [key, value] of filterEntries) { - const isPlainObject = - value !== null && - typeof value === 'object' && - !Array.isArray(value); - - if (isPlainObject) { - const opEntries = Object.entries(value as Record); - const hasDollarOperator = opEntries.some(([op]) => op.startsWith('$')); - - if (hasDollarOperator) { - for (const [rawOp, opValue] of opEntries) { - const mappedOp = - operatorMap[rawOp as keyof typeof operatorMap] ?? - rawOp.replace(/^\$/, ''); - filters.push([key, mappedOp, opValue]); - } - continue; - } - } - - // Fallback: treat as simple equality - filters.push([key, '=', value]); - } - - objectqlParams.filter = filters as FilterExpression; - } + queryOptions.filters = params.$filter; } // Convert $orderby to sort if (params.$orderby) { - objectqlParams.sort = Object.entries(params.$orderby).map( - ([key, dir]) => [key, dir] as [string, 'asc' | 'desc'] - ); + const sortEntries = Object.entries(params.$orderby); + if (sortEntries.length > 0) { + // Convert to array format expected by ObjectStack + queryOptions.sort = sortEntries.map(([field, direction]) => + `${field}:${direction}` + ); + } } // Convert pagination if (params.$skip !== undefined) { - objectqlParams.skip = params.$skip; + queryOptions.skip = params.$skip; } if (params.$top !== undefined) { - objectqlParams.limit = params.$top; + queryOptions.top = params.$top; } - return objectqlParams; + return queryOptions; } /** @@ -237,20 +187,22 @@ export class ObjectQLDataSource implements DataSource { * @returns Promise resolving to query result with data and metadata */ async find(resource: string, params?: QueryParams): Promise> { - const objectqlParams = this.convertParams(params); + const queryOptions = this.convertParams(params); try { - const response = await this.client.list(resource, objectqlParams); + const response = await this.client.data.find(resource, queryOptions); - const data = response.items || []; - const total = response.meta?.total; + const data = response.value || []; + const total = response.count; return { data, total, - page: response.meta?.page, - pageSize: objectqlParams.limit, - hasMore: response.meta?.has_next, + page: params?.$skip && params?.$top + ? Math.floor(params.$skip / params.$top) + 1 + : undefined, + pageSize: queryOptions.top, + hasMore: total !== undefined && data.length < total, }; } catch (err: any) { // Convert SDK errors to APIError format @@ -277,13 +229,13 @@ export class ObjectQLDataSource implements DataSource { params?: QueryParams ): Promise { try { - const response = await this.client.get(resource, id); + const response = await this.client.data.get(resource, String(id)); // Return the item data, filtering fields if requested if (params?.$select && response) { const filtered: any = {}; for (const field of params.$select) { - if (field in response) { + if (response && typeof response === 'object' && field in response) { filtered[field] = (response as any)[field]; } } @@ -293,7 +245,8 @@ export class ObjectQLDataSource implements DataSource { return response ? (response as T) : null; } catch (err: any) { // Return null for not found errors - if (err.code === 'NOT_FOUND' || err.status === 404) { + // ObjectStack client throws with different error format + if (err.message?.includes('404') || err.status === 404) { return null; } @@ -316,7 +269,7 @@ export class ObjectQLDataSource implements DataSource { */ async create(resource: string, data: Partial): Promise { try { - const response = await this.client.create(resource, data); + const response = await this.client.data.create(resource, data); return response as T; } catch (err: any) { throw { @@ -342,7 +295,7 @@ export class ObjectQLDataSource implements DataSource { data: Partial ): Promise { try { - const response = await this.client.update(resource, id, data); + const response = await this.client.data.update(resource, String(id), data); return response as T; } catch (err: any) { throw { @@ -363,7 +316,7 @@ export class ObjectQLDataSource implements DataSource { */ async delete(resource: string, id: string | number): Promise { try { - const response = await this.client.delete(resource, id); + const response = await this.client.data.delete(resource, String(id)); return response.success ?? true; } catch (err: any) { throw { @@ -384,7 +337,7 @@ export class ObjectQLDataSource implements DataSource { async getObjectSchema(objectName: string): Promise { try { // Use the Metadata API client to fetch object metadata - const response = await this.metadataClient.getObject(objectName); + const response = await this.client.meta.getObject(objectName); return response; } catch (err: any) { throw { @@ -411,15 +364,17 @@ export class ObjectQLDataSource implements DataSource { ): Promise { try { if (operation === 'create') { - const response = await this.client.createMany(resource, data); - return response.items || []; + const response = await this.client.data.createMany(resource, data); + return response || []; } else if (operation === 'update') { - // Fallback implementation: iterate and call single-record update + // For update: extract IDs and update data if (!Array.isArray(data)) { throw new Error('Bulk update requires array of records'); } - const results: T[] = []; + const ids: string[] = []; + let updateData: Partial = {}; + for (const item of data) { const record: any = item as any; const id = record?.id ?? record?._id; @@ -428,20 +383,30 @@ export class ObjectQLDataSource implements DataSource { 'Bulk update requires each item to include an `id` or `_id` field.' ); } - // Do not send id as part of the update payload - const { id: _omitId, _id: _omitUnderscore, ...updateData } = record; - const updated = await this.client.update(resource, id, updateData); + ids.push(String(id)); + // Use the first record's data for the update (excluding id fields) + const { id: _omitId, _id: _omitUnderscore, ...rest } = record; + updateData = rest; + } + + await this.client.data.updateMany(resource, ids, updateData); + + // Return updated records by fetching them + const results: T[] = []; + for (const id of ids) { + const updated = await this.client.data.get(resource, id); if (updated !== undefined && updated !== null) { results.push(updated as T); } } return results; } else if (operation === 'delete') { - // Fallback implementation: iterate and call single-record delete + // For delete: extract IDs if (!Array.isArray(data)) { throw new Error('Bulk delete requires array of records or IDs'); } + const ids: string[] = []; for (const item of data) { const record: any = item as any; // Support both direct ID values and objects with id/_id field @@ -453,8 +418,10 @@ export class ObjectQLDataSource implements DataSource { 'Bulk delete requires each item to include an `id` or `_id` field or be an id value.' ); } - await this.client.delete(resource, id); + ids.push(String(id)); } + + await this.client.data.deleteMany(resource, ids); // For delete operations, we return an empty array by convention return []; } diff --git a/packages/data-objectql/src/__tests__/ObjectQLDataSource.test.ts b/packages/data-objectql/src/__tests__/ObjectQLDataSource.test.ts index 6ca8e98..e6ed2f9 100644 --- a/packages/data-objectql/src/__tests__/ObjectQLDataSource.test.ts +++ b/packages/data-objectql/src/__tests__/ObjectQLDataSource.test.ts @@ -30,13 +30,11 @@ describe('ObjectQLDataSource', () => { describe('find', () => { it('should fetch multiple records', async () => { const mockData = { - items: [ + value: [ { _id: '1', name: 'John' }, { _id: '2', name: 'Jane' }, ], - meta: { - total: 2, - } + count: 2 }; (global.fetch as any).mockResolvedValueOnce({ @@ -46,12 +44,12 @@ describe('ObjectQLDataSource', () => { const result = await dataSource.find('contacts'); - expect(result.data).toEqual(mockData.items); + expect(result.data).toEqual(mockData.value); expect(result.total).toBe(2); }); - it('should convert universal query params to ObjectQL format', async () => { - const mockData = { items: [], meta: { total: 0 } }; + it('should convert universal query params to ObjectStack format', async () => { + const mockData = { value: [], count: 0 }; (global.fetch as any).mockResolvedValueOnce({ ok: true, @@ -69,13 +67,15 @@ describe('ObjectQLDataSource', () => { const fetchCall = (global.fetch as any).mock.calls[0]; const url = fetchCall[0]; - expect(url).toContain('filter='); + // ObjectStack client uses different parameter names expect(url).toContain('skip=10'); - expect(url).toContain('limit=20'); + expect(url).toContain('top=20'); + expect(url).toContain('sort=created'); + expect(url).toContain('select=name'); }); it('should convert MongoDB-like operators in filters', async () => { - const mockData = { items: [], meta: { total: 0 } }; + const mockData = { value: [], count: 0 }; (global.fetch as any).mockResolvedValueOnce({ ok: true, @@ -92,24 +92,14 @@ describe('ObjectQLDataSource', () => { const fetchCall = (global.fetch as any).mock.calls[0]; const url = fetchCall[0]; - // Verify the filter parameter is present - expect(url).toContain('filter='); - - // The filter should be encoded as a JSON array with operators - const urlObj = new URL(url, 'http://localhost'); - const filterParam = urlObj.searchParams.get('filter'); - if (filterParam) { - const filter = JSON.parse(filterParam); - // Should have converted to FilterExpression format - expect(Array.isArray(filter)).toBe(true); - // Should have converted $gte to '>=' and $lte to '<=' - expect(filter.some((f: any) => f[1] === '>=')).toBe(true); - expect(filter.some((f: any) => f[1] === '<=')).toBe(true); - } + // Verify the filter parameters are present in the URL + // ObjectStack client flattens filters into query params + expect(url).toContain('age='); + expect(url).toContain('status='); }); it('should include authentication token in headers', async () => { - const mockData = { items: [] }; + const mockData = { value: [] }; (global.fetch as any).mockResolvedValueOnce({ ok: true, @@ -197,9 +187,8 @@ describe('ObjectQLDataSource', () => { const fetchCall = (global.fetch as any).mock.calls[0]; const options = fetchCall[1]; - // The SDK uses PUT method for updates (not PATCH) - // This is the standard behavior of @objectql/sdk's DataApiClient - expect(options.method).toBe('PUT'); + // The ObjectStack client uses PUT or PATCH method for updates + expect(['PUT', 'PATCH']).toContain(options.method); expect(options.body).toBe(JSON.stringify(updates)); }); }); @@ -228,12 +217,10 @@ describe('ObjectQLDataSource', () => { { name: 'Contact 1' }, { name: 'Contact 2' }, ]; - const createdRecords = { - items: [ - { _id: '1', name: 'Contact 1' }, - { _id: '2', name: 'Contact 2' }, - ] - }; + const createdRecords = [ + { _id: '1', name: 'Contact 1' }, + { _id: '2', name: 'Contact 2' }, + ]; (global.fetch as any).mockResolvedValueOnce({ ok: true, @@ -242,7 +229,7 @@ describe('ObjectQLDataSource', () => { const result = await dataSource.bulk('contacts', 'create', bulkData); - expect(result).toEqual(createdRecords.items); + expect(result).toEqual(createdRecords); const fetchCall = (global.fetch as any).mock.calls[0]; const options = fetchCall[1]; diff --git a/packages/plugin-object/package.json b/packages/plugin-object/package.json index 4e187b2..82a2a46 100644 --- a/packages/plugin-object/package.json +++ b/packages/plugin-object/package.json @@ -48,8 +48,6 @@ "@object-ui/react": "workspace:*", "@object-ui/components": "workspace:*", "@object-ui/data-objectql": "workspace:*", - "@objectql/sdk": "^3.0.1", - "@objectql/types": "^3.0.1", "lucide-react": "^0.562.0", "clsx": "^2.1.1", "tailwind-merge": "^3.4.0" diff --git a/packages/plugin-object/src/ObjectForm.tsx b/packages/plugin-object/src/ObjectForm.tsx index a3dda87..c70f36f 100644 --- a/packages/plugin-object/src/ObjectForm.tsx +++ b/packages/plugin-object/src/ObjectForm.tsx @@ -292,7 +292,7 @@ export const ObjectForm: React.FC = ({ * `select`). If a field type is not explicitly mapped, the function falls * back to the generic `"input"` type. * - * Updated to support all field types from @objectql/types v3.0.1: + * Updated to support all field types from ObjectStack Protocol: * text, textarea, markdown, html, select, date, datetime, time, number, * currency, percent, boolean, email, phone, url, image, file, location, * lookup, master_detail, password, formula, summary, auto_number, object, diff --git a/packages/plugin-object/vite.config.ts b/packages/plugin-object/vite.config.ts index 753885b..aacde60 100644 --- a/packages/plugin-object/vite.config.ts +++ b/packages/plugin-object/vite.config.ts @@ -36,8 +36,6 @@ export default defineConfig({ '@object-ui/react', '@object-ui/components', '@object-ui/data-objectql', - '@objectql/sdk', - '@objectql/types', ], output: { globals: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c4073a..e18e1a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -473,12 +473,6 @@ importers: '@object-ui/types': specifier: workspace:* version: link:../types - '@objectql/sdk': - specifier: ^3.0.1 - version: 3.0.1 - '@objectql/types': - specifier: ^3.0.1 - version: 3.0.1 '@objectstack/client': specifier: ^0.1.1 version: 0.1.1 @@ -728,12 +722,6 @@ importers: '@object-ui/types': specifier: workspace:* version: link:../types - '@objectql/sdk': - specifier: ^3.0.1 - version: 3.0.1 - '@objectql/types': - specifier: ^3.0.1 - version: 3.0.1 clsx: specifier: ^2.1.1 version: 2.1.1 @@ -1883,12 +1871,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@objectql/sdk@3.0.1': - resolution: {integrity: sha512-SKANOy3w4keumcHO2yRuyV3eiaDI3XSzugCgh8MnS3ssFsthI88glxZdim9Af6RYcBNo+Ir0CjjYMDuNsF0S0w==} - - '@objectql/types@3.0.1': - resolution: {integrity: sha512-L1G8WyZ8TEFatTaPMsSU6zDjCcaFQ5IN1vv3P0j5qwJhIBFUgoO6kl1HpB+CffKQH0F3z9iSpAlGjqExwhHTmw==} - '@objectstack/client@0.1.1': resolution: {integrity: sha512-H8R06QqxA3V7gsAaElGgJLJLJmIG7GWjWM3T8yKHPslEFlz44eFoETzMUf3vQ8IpLGcc4Bqi0UvetUQSYzpZ4g==} @@ -7435,12 +7417,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@objectql/sdk@3.0.1': - dependencies: - '@objectql/types': 3.0.1 - - '@objectql/types@3.0.1': {} - '@objectstack/client@0.1.1': dependencies: '@objectstack/spec': 0.1.2