@object-ui/data-objectstack 15.0.0 → 16.1.0

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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ObjectStackClient } from '@objectstack/client';
2
- import { DataSource, QueryParams, QueryResult, MutationEvent, ImportRequestOptions, ImportRecordsResult, CreateImportJobResult, ImportJobProgressInfo, ImportJobResultsInfo, ListImportJobsOptions, ImportJobSummaryInfo, ImportJobUndoResult, ExportDownloadRequest, FileUploadResult } from '@object-ui/types';
2
+ import { DataSource, QueryParams, QueryResult, MutationEvent, BatchTransactionOperation, ImportRequestOptions, ImportRecordsResult, CreateImportJobResult, ImportJobProgressInfo, ImportJobResultsInfo, ListImportJobsOptions, ImportJobSummaryInfo, ImportJobUndoResult, ExportDownloadRequest, FileUploadResult } from '@object-ui/types';
3
3
  export { FileUploadResult } from '@object-ui/types';
4
4
 
5
5
  /**
@@ -1182,6 +1182,26 @@ declare function calculateAutoLayout(items: Array<{
1182
1182
  declare function getSharedDiscovery(baseUrl: string, fetcher: () => Promise<unknown>): Promise<unknown>;
1183
1183
  /** Test/dev helper to drop the cache (e.g. on logout or origin change). */
1184
1184
  declare function clearSharedDiscoveryCache(): void;
1185
+ /**
1186
+ * Read the cross-object atomic-batch capability from a `discovery` document
1187
+ * (framework #3298 / objectui #2693). The server advertises it hierarchically
1188
+ * under `capabilities.transactionalBatch.enabled`; the published
1189
+ * `@objectstack/client` also accepts the flat `capabilities.transactionalBatch:
1190
+ * boolean` form and normalizes the two — mirror that here so the adapter reads
1191
+ * the same bit regardless of which shape reaches it.
1192
+ *
1193
+ * Returns:
1194
+ * - `true` — the backend GUARANTEES an atomic `/batch` (declared === enforced,
1195
+ * i.e. the route is mounted AND the runtime can honour a transaction): the
1196
+ * client may drop its non-atomic fallback and treat any batch failure as a
1197
+ * real error.
1198
+ * - `false` — the backend explicitly does NOT (route absent, or a runtime that
1199
+ * can't open a transaction).
1200
+ * - `undefined` — the capability is absent, i.e. the backend predates #3298;
1201
+ * the caller must keep the legacy runtime-probe fallback (we can't tell
1202
+ * whether `/batch` exists without trying it).
1203
+ */
1204
+ declare function readTransactionalBatchCapability(discovery: unknown): boolean | undefined;
1185
1205
  /**
1186
1206
  * Detect "missing resource" errors regardless of where they originate.
1187
1207
  *
@@ -1311,6 +1331,8 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1311
1331
  private fetchImpl;
1312
1332
  private inflightFinds;
1313
1333
  private missingResources;
1334
+ private batchUnsupported;
1335
+ private atomicBatchCapability;
1314
1336
  private mutationListeners;
1315
1337
  constructor(config: {
1316
1338
  baseUrl: string;
@@ -1440,19 +1462,53 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1440
1462
  * @returns Promise resolving to array of results
1441
1463
  */
1442
1464
  /**
1443
- * Cross-object transactional batch (ObjectStack #1604). Runs the operations
1444
- * in ONE server transaction — commit all or roll back all. A field value of
1445
- * `{ $ref: <earlier op index> }` resolves to that op's created id, so a child
1446
- * can reference its parent created earlier in the same batch (master-detail).
1447
- */
1448
- batchTransaction(operations: Array<{
1449
- object: string;
1450
- action?: 'create' | 'update' | 'delete';
1451
- data?: any;
1452
- id?: string;
1453
- }>): Promise<{
1465
+ * Cross-object transactional batch (ObjectStack #1604 / ADR-0034 item 4).
1466
+ * Runs the operations in ONE server transaction — commit all or roll back
1467
+ * all. A field value of `{ $ref: <earlier op index> }` resolves to that op's
1468
+ * created id, so a child can reference its parent created earlier in the same
1469
+ * batch (master-detail).
1470
+ *
1471
+ * Transport: the published `@objectstack/client` SDK method
1472
+ * `data.batchTransaction` (framework #3271; shipped since client v16, our
1473
+ * dependency floor). Per AGENTS.md §7 data always flows through the client —
1474
+ * never a hand-rolled `fetch('/api/v1/batch')`.
1475
+ *
1476
+ * Fallback decision — declarative capability negotiation (framework #3298 /
1477
+ * objectui #2693). At connect() we read `capabilities.transactionalBatch`
1478
+ * from discovery:
1479
+ * - Declared `true` → the backend GUARANTEES atomicity (declared ===
1480
+ * enforced). We TRUST it: any batch failure — including 404/405/501 —
1481
+ * surfaces as a real error. No non-atomic client-side compensation. This
1482
+ * is the path modern backends take.
1483
+ * - Declared `false`, or ABSENT (backend predates #3298) → we can't rely on
1484
+ * server atomicity, so we keep the legacy behaviour: on 404/405 (no
1485
+ * endpoint) or 501 (runtime without transactions) degrade to the
1486
+ * client-side, NON-atomic {@link emulateBatchTransaction} so a save is
1487
+ * still possible. Removing that here would regress older backends from
1488
+ * "saves, less safe" to "no save path" (#2679 compatibility constraint).
1489
+ * The non-atomic fallback stays isolated to THIS adapter.
1490
+ */
1491
+ batchTransaction(operations: BatchTransactionOperation[]): Promise<{
1454
1492
  results: any[];
1455
1493
  }>;
1494
+ /** True for statuses that mean "this backend can't do a transactional batch". */
1495
+ private batchStatusUnsupported;
1496
+ /** Best-effort HTTP status extraction from a thrown SDK/client error. */
1497
+ private errorStatusOf;
1498
+ /** Mark the endpoint unsupported (warn once) and serve via emulation. */
1499
+ private fallbackToEmulation;
1500
+ /**
1501
+ * Emit one MutationEvent per committed operation so the invalidation bus
1502
+ * (#2269) sees writes that went through /batch exactly like single
1503
+ * create/update/delete calls — master-detail ModalForm saves otherwise leave
1504
+ * related lists and count badges stale (#2582). `results` is index-aligned
1505
+ * with `operations`; creates take id/record from the server echo.
1506
+ *
1507
+ * Only called on the server-committed paths. The emulation branch drives the
1508
+ * adapter's own create/update/delete primitives, which already emit — so it
1509
+ * must NOT be routed through here, or events would double-fire.
1510
+ */
1511
+ private emitBatchMutations;
1456
1512
  bulk(resource: string, operation: 'create' | 'update' | 'delete', data: Partial<T>[]): Promise<T[]>;
1457
1513
  /**
1458
1514
  * Bulk-import raw spreadsheet rows in a single server round-trip via
@@ -1640,7 +1696,16 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1640
1696
  * Filters by `data.object === objectName` (or top-level `object`)
1641
1697
  * client-side because the metadata index is name-only, not field-typed.
1642
1698
  */
1643
- listViews(objectName: string): Promise<any[]>;
1699
+ listViews(objectName: string, options?: {
1700
+ previewDrafts?: boolean;
1701
+ }): Promise<any[]>;
1702
+ /**
1703
+ * Build a {@link MetadataClient} bound to this adapter's server + auth. Used
1704
+ * by draft-aware reads (`listViews({ previewDrafts })`) so the `/meta` route,
1705
+ * `?preview=draft` flag, and environment scoping live in the SDK rather than
1706
+ * being hand-assembled at each call site (#2767 P3).
1707
+ */
1708
+ private metadataClient;
1644
1709
  /**
1645
1710
  * List registered import `mapping` artifacts targeting a given object
1646
1711
  * (framework #2611). Reads the `mapping` metadata kind via the overlay API
@@ -1873,4 +1938,4 @@ declare function createObjectStackAdapter<T = unknown>(config: {
1873
1938
  reconnectDelay?: number;
1874
1939
  }): DataSource<T>;
1875
1940
 
1876
- export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConcurrentUpdateError, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, type MetadataAuditEntry, type MetadataAuditResponse, MetadataClient, type MetadataClientConfig, type MetadataDeleteOptions, type MetadataDiagnostics, type MetadataDiagnosticsEntry, type MetadataDiagnosticsOptions, type MetadataDiagnosticsSummary, type MetadataDraftHeader, type MetadataError, type MetadataGetOptions, type MetadataHistoryOptions, type MetadataLayered, type MetadataListOptions, MetadataNotFoundError, type MetadataReference, type MetadataSaveOptions, type MetadataValidationIssue, ObjectStackAdapter, ObjectStackError, type ObjectStackUserStateAdapterOptions, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, type UserDataAdapter, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, createObjectStackUserStateAdapter, generateContractManifest, getSharedDiscovery, is404Error, isConcurrentUpdateError, isErrorType, isObjectStackError, normaliseClientError, snapToGrid, validatePluginContract };
1941
+ export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConcurrentUpdateError, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, type MetadataAuditEntry, type MetadataAuditResponse, MetadataClient, type MetadataClientConfig, type MetadataDeleteOptions, type MetadataDiagnostics, type MetadataDiagnosticsEntry, type MetadataDiagnosticsOptions, type MetadataDiagnosticsSummary, type MetadataDraftHeader, type MetadataError, type MetadataGetOptions, type MetadataHistoryOptions, type MetadataLayered, type MetadataListOptions, MetadataNotFoundError, type MetadataReference, type MetadataSaveOptions, type MetadataValidationIssue, ObjectStackAdapter, ObjectStackError, type ObjectStackUserStateAdapterOptions, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, type UserDataAdapter, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, createObjectStackUserStateAdapter, generateContractManifest, getSharedDiscovery, is404Error, isConcurrentUpdateError, isErrorType, isObjectStackError, normaliseClientError, readTransactionalBatchCapability, snapToGrid, validatePluginContract };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ObjectStackClient } from '@objectstack/client';
2
- import { DataSource, QueryParams, QueryResult, MutationEvent, ImportRequestOptions, ImportRecordsResult, CreateImportJobResult, ImportJobProgressInfo, ImportJobResultsInfo, ListImportJobsOptions, ImportJobSummaryInfo, ImportJobUndoResult, ExportDownloadRequest, FileUploadResult } from '@object-ui/types';
2
+ import { DataSource, QueryParams, QueryResult, MutationEvent, BatchTransactionOperation, ImportRequestOptions, ImportRecordsResult, CreateImportJobResult, ImportJobProgressInfo, ImportJobResultsInfo, ListImportJobsOptions, ImportJobSummaryInfo, ImportJobUndoResult, ExportDownloadRequest, FileUploadResult } from '@object-ui/types';
3
3
  export { FileUploadResult } from '@object-ui/types';
4
4
 
5
5
  /**
@@ -1182,6 +1182,26 @@ declare function calculateAutoLayout(items: Array<{
1182
1182
  declare function getSharedDiscovery(baseUrl: string, fetcher: () => Promise<unknown>): Promise<unknown>;
1183
1183
  /** Test/dev helper to drop the cache (e.g. on logout or origin change). */
1184
1184
  declare function clearSharedDiscoveryCache(): void;
1185
+ /**
1186
+ * Read the cross-object atomic-batch capability from a `discovery` document
1187
+ * (framework #3298 / objectui #2693). The server advertises it hierarchically
1188
+ * under `capabilities.transactionalBatch.enabled`; the published
1189
+ * `@objectstack/client` also accepts the flat `capabilities.transactionalBatch:
1190
+ * boolean` form and normalizes the two — mirror that here so the adapter reads
1191
+ * the same bit regardless of which shape reaches it.
1192
+ *
1193
+ * Returns:
1194
+ * - `true` — the backend GUARANTEES an atomic `/batch` (declared === enforced,
1195
+ * i.e. the route is mounted AND the runtime can honour a transaction): the
1196
+ * client may drop its non-atomic fallback and treat any batch failure as a
1197
+ * real error.
1198
+ * - `false` — the backend explicitly does NOT (route absent, or a runtime that
1199
+ * can't open a transaction).
1200
+ * - `undefined` — the capability is absent, i.e. the backend predates #3298;
1201
+ * the caller must keep the legacy runtime-probe fallback (we can't tell
1202
+ * whether `/batch` exists without trying it).
1203
+ */
1204
+ declare function readTransactionalBatchCapability(discovery: unknown): boolean | undefined;
1185
1205
  /**
1186
1206
  * Detect "missing resource" errors regardless of where they originate.
1187
1207
  *
@@ -1311,6 +1331,8 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1311
1331
  private fetchImpl;
1312
1332
  private inflightFinds;
1313
1333
  private missingResources;
1334
+ private batchUnsupported;
1335
+ private atomicBatchCapability;
1314
1336
  private mutationListeners;
1315
1337
  constructor(config: {
1316
1338
  baseUrl: string;
@@ -1440,19 +1462,53 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1440
1462
  * @returns Promise resolving to array of results
1441
1463
  */
1442
1464
  /**
1443
- * Cross-object transactional batch (ObjectStack #1604). Runs the operations
1444
- * in ONE server transaction — commit all or roll back all. A field value of
1445
- * `{ $ref: <earlier op index> }` resolves to that op's created id, so a child
1446
- * can reference its parent created earlier in the same batch (master-detail).
1447
- */
1448
- batchTransaction(operations: Array<{
1449
- object: string;
1450
- action?: 'create' | 'update' | 'delete';
1451
- data?: any;
1452
- id?: string;
1453
- }>): Promise<{
1465
+ * Cross-object transactional batch (ObjectStack #1604 / ADR-0034 item 4).
1466
+ * Runs the operations in ONE server transaction — commit all or roll back
1467
+ * all. A field value of `{ $ref: <earlier op index> }` resolves to that op's
1468
+ * created id, so a child can reference its parent created earlier in the same
1469
+ * batch (master-detail).
1470
+ *
1471
+ * Transport: the published `@objectstack/client` SDK method
1472
+ * `data.batchTransaction` (framework #3271; shipped since client v16, our
1473
+ * dependency floor). Per AGENTS.md §7 data always flows through the client —
1474
+ * never a hand-rolled `fetch('/api/v1/batch')`.
1475
+ *
1476
+ * Fallback decision — declarative capability negotiation (framework #3298 /
1477
+ * objectui #2693). At connect() we read `capabilities.transactionalBatch`
1478
+ * from discovery:
1479
+ * - Declared `true` → the backend GUARANTEES atomicity (declared ===
1480
+ * enforced). We TRUST it: any batch failure — including 404/405/501 —
1481
+ * surfaces as a real error. No non-atomic client-side compensation. This
1482
+ * is the path modern backends take.
1483
+ * - Declared `false`, or ABSENT (backend predates #3298) → we can't rely on
1484
+ * server atomicity, so we keep the legacy behaviour: on 404/405 (no
1485
+ * endpoint) or 501 (runtime without transactions) degrade to the
1486
+ * client-side, NON-atomic {@link emulateBatchTransaction} so a save is
1487
+ * still possible. Removing that here would regress older backends from
1488
+ * "saves, less safe" to "no save path" (#2679 compatibility constraint).
1489
+ * The non-atomic fallback stays isolated to THIS adapter.
1490
+ */
1491
+ batchTransaction(operations: BatchTransactionOperation[]): Promise<{
1454
1492
  results: any[];
1455
1493
  }>;
1494
+ /** True for statuses that mean "this backend can't do a transactional batch". */
1495
+ private batchStatusUnsupported;
1496
+ /** Best-effort HTTP status extraction from a thrown SDK/client error. */
1497
+ private errorStatusOf;
1498
+ /** Mark the endpoint unsupported (warn once) and serve via emulation. */
1499
+ private fallbackToEmulation;
1500
+ /**
1501
+ * Emit one MutationEvent per committed operation so the invalidation bus
1502
+ * (#2269) sees writes that went through /batch exactly like single
1503
+ * create/update/delete calls — master-detail ModalForm saves otherwise leave
1504
+ * related lists and count badges stale (#2582). `results` is index-aligned
1505
+ * with `operations`; creates take id/record from the server echo.
1506
+ *
1507
+ * Only called on the server-committed paths. The emulation branch drives the
1508
+ * adapter's own create/update/delete primitives, which already emit — so it
1509
+ * must NOT be routed through here, or events would double-fire.
1510
+ */
1511
+ private emitBatchMutations;
1456
1512
  bulk(resource: string, operation: 'create' | 'update' | 'delete', data: Partial<T>[]): Promise<T[]>;
1457
1513
  /**
1458
1514
  * Bulk-import raw spreadsheet rows in a single server round-trip via
@@ -1640,7 +1696,16 @@ declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
1640
1696
  * Filters by `data.object === objectName` (or top-level `object`)
1641
1697
  * client-side because the metadata index is name-only, not field-typed.
1642
1698
  */
1643
- listViews(objectName: string): Promise<any[]>;
1699
+ listViews(objectName: string, options?: {
1700
+ previewDrafts?: boolean;
1701
+ }): Promise<any[]>;
1702
+ /**
1703
+ * Build a {@link MetadataClient} bound to this adapter's server + auth. Used
1704
+ * by draft-aware reads (`listViews({ previewDrafts })`) so the `/meta` route,
1705
+ * `?preview=draft` flag, and environment scoping live in the SDK rather than
1706
+ * being hand-assembled at each call site (#2767 P3).
1707
+ */
1708
+ private metadataClient;
1644
1709
  /**
1645
1710
  * List registered import `mapping` artifacts targeting a given object
1646
1711
  * (framework #2611). Reads the `mapping` metadata kind via the overlay API
@@ -1873,4 +1938,4 @@ declare function createObjectStackAdapter<T = unknown>(config: {
1873
1938
  reconnectDelay?: number;
1874
1939
  }): DataSource<T>;
1875
1940
 
1876
- export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConcurrentUpdateError, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, type MetadataAuditEntry, type MetadataAuditResponse, MetadataClient, type MetadataClientConfig, type MetadataDeleteOptions, type MetadataDiagnostics, type MetadataDiagnosticsEntry, type MetadataDiagnosticsOptions, type MetadataDiagnosticsSummary, type MetadataDraftHeader, type MetadataError, type MetadataGetOptions, type MetadataHistoryOptions, type MetadataLayered, type MetadataListOptions, MetadataNotFoundError, type MetadataReference, type MetadataSaveOptions, type MetadataValidationIssue, ObjectStackAdapter, ObjectStackError, type ObjectStackUserStateAdapterOptions, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, type UserDataAdapter, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, createObjectStackUserStateAdapter, generateContractManifest, getSharedDiscovery, is404Error, isConcurrentUpdateError, isErrorType, isObjectStackError, normaliseClientError, snapToGrid, validatePluginContract };
1941
+ export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConcurrentUpdateError, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, type MetadataAuditEntry, type MetadataAuditResponse, MetadataClient, type MetadataClientConfig, type MetadataDeleteOptions, type MetadataDiagnostics, type MetadataDiagnosticsEntry, type MetadataDiagnosticsOptions, type MetadataDiagnosticsSummary, type MetadataDraftHeader, type MetadataError, type MetadataGetOptions, type MetadataHistoryOptions, type MetadataLayered, type MetadataListOptions, MetadataNotFoundError, type MetadataReference, type MetadataSaveOptions, type MetadataValidationIssue, ObjectStackAdapter, ObjectStackError, type ObjectStackUserStateAdapterOptions, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, type UserDataAdapter, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, createObjectStackUserStateAdapter, generateContractManifest, getSharedDiscovery, is404Error, isConcurrentUpdateError, isErrorType, isObjectStackError, normaliseClientError, readTransactionalBatchCapability, snapToGrid, validatePluginContract };