@centrali-io/centrali-sdk 5.4.0 → 5.5.1
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/README.md +89 -14
- package/dist/index.d.ts +234 -28
- package/dist/index.js +289 -80
- package/dist/query-types.d.ts +187 -0
- package/dist/query-types.js +137 -0
- package/dist/scripts/smoke-types.d.ts +12 -0
- package/dist/scripts/smoke-types.js +102 -0
- package/index.ts +387 -37
- package/package.json +3 -1
- package/query-types.ts +394 -0
- package/scripts/smoke-types.ts +128 -0
- package/scripts/sync-query-types.mjs +40 -0
package/index.ts
CHANGED
|
@@ -797,10 +797,74 @@ export interface ExpandOptions {
|
|
|
797
797
|
*/
|
|
798
798
|
export interface GetRecordOptions extends ExpandOptions {}
|
|
799
799
|
|
|
800
|
+
// =====================================================
|
|
801
|
+
// Canonical query types (CEN-1194 — Phase 1 query foundation)
|
|
802
|
+
// =====================================================
|
|
803
|
+
// Re-exports the canonical `QueryDefinition` surface from @centrali/query.
|
|
804
|
+
// `query-types.ts` is generated from `services/backend/shared/query/src/types.ts`
|
|
805
|
+
// by `scripts/sync-query-types.mjs` (runs on prebuild). Do not edit it by hand.
|
|
806
|
+
//
|
|
807
|
+
// Use these for new code:
|
|
808
|
+
// - `client.records.query(resource, definition)` — POST /records/query
|
|
809
|
+
// - `client.records.list(resource, urlOpts?)` — GET adapter
|
|
810
|
+
// - `client.records.search(resource, text, opts?)` — sugar over `{ text }`
|
|
811
|
+
// - `client.records.test(resource, definition)` — authoring dry-run
|
|
812
|
+
// - `client.queryRecords<T>(resource, definition)` — top-level convenience
|
|
813
|
+
//
|
|
814
|
+
// Saved queries: `client.savedQueries.*` is the canonical namespace, routing
|
|
815
|
+
// through the `/saved-queries/*` HTTP endpoints (Phase 4 — CEN-1198).
|
|
816
|
+
// `client.smartQueries.*` is preserved as a deprecated alias during the
|
|
817
|
+
// deprecation window.
|
|
818
|
+
//
|
|
819
|
+
// The legacy `FilterOperators` / `QueryRecordOptions` block below is preserved
|
|
820
|
+
// for the GET adapter (`client.records.list()` and the legacy
|
|
821
|
+
// `client.queryRecords(slug, urlOpts)` form). Migration guidance for the
|
|
822
|
+
// canonical operator vocabulary lives in
|
|
823
|
+
// `docs/maintainers/overview/query-foundation.md`.
|
|
824
|
+
export * from './query-types';
|
|
825
|
+
import type {
|
|
826
|
+
QueryDefinition,
|
|
827
|
+
QueryResult,
|
|
828
|
+
WhereExpression,
|
|
829
|
+
SortClause,
|
|
830
|
+
PageClause,
|
|
831
|
+
SelectClause,
|
|
832
|
+
QueryVariableDefinition,
|
|
833
|
+
ScalarValue,
|
|
834
|
+
FieldConditionMap,
|
|
835
|
+
FieldCondition,
|
|
836
|
+
} from './query-types';
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Discriminator for the dual-shape `client.queryRecords(...)` overload.
|
|
840
|
+
*
|
|
841
|
+
* Returns `true` if the argument is a canonical `QueryDefinition`. The
|
|
842
|
+
* marker is **the presence of `resource`** — that field is required by the
|
|
843
|
+
* canonical contract (`docs/superpowers/specs/2026-04-25-query-foundation-contract.md` §3)
|
|
844
|
+
* and isn't a legal key in the legacy `QueryRecordOptions` URL-param shape.
|
|
845
|
+
*
|
|
846
|
+
* Callers who want to omit `resource` (relying on the first argument to fill
|
|
847
|
+
* it in) should use `client.records.query(resource, definition)` directly,
|
|
848
|
+
* which has its own backfill behavior.
|
|
849
|
+
*/
|
|
850
|
+
function isCanonicalQueryDefinition(arg: any): arg is QueryDefinition {
|
|
851
|
+
return (
|
|
852
|
+
arg !== null &&
|
|
853
|
+
typeof arg === 'object' &&
|
|
854
|
+
typeof arg.resource === 'string'
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
|
|
800
858
|
/**
|
|
801
|
-
* Filter operators for querying records.
|
|
859
|
+
* Filter operators for querying records via the legacy GET adapter.
|
|
860
|
+
*
|
|
802
861
|
* Pass filters at the TOP LEVEL of query params (not nested under 'filter').
|
|
803
|
-
* Use bracket notation for operators: 'data.field[operator]': value
|
|
862
|
+
* Use bracket notation for operators: `'data.field[operator]': value`
|
|
863
|
+
*
|
|
864
|
+
* @deprecated Since 5.5.0. Prefer canonical `FieldCondition` from
|
|
865
|
+
* `@centrali-io/centrali-sdk` (re-exported above) and use `client.records.query()`
|
|
866
|
+
* with a `QueryDefinition` body. This shape stays for back-compat with
|
|
867
|
+
* `client.queryRecords(slug, options)` / `client.records.list()`.
|
|
804
868
|
*
|
|
805
869
|
* @example
|
|
806
870
|
* // Simple equality - just use the field name
|
|
@@ -865,7 +929,7 @@ export interface DateWindowOption {
|
|
|
865
929
|
}
|
|
866
930
|
|
|
867
931
|
/**
|
|
868
|
-
* Options for querying records.
|
|
932
|
+
* Options for querying records via the GET adapter.
|
|
869
933
|
*
|
|
870
934
|
* Supports two filter styles:
|
|
871
935
|
*
|
|
@@ -884,6 +948,14 @@ export interface DateWindowOption {
|
|
|
884
948
|
* Both styles are supported and can be mixed. Use `data.` prefix for custom fields.
|
|
885
949
|
* System fields (`id`, `createdAt`, `updatedAt`, `status`) don't need the prefix.
|
|
886
950
|
*
|
|
951
|
+
* @deprecated Since 5.5.0. This is the URL-param shape consumed by
|
|
952
|
+
* `client.records.list()` and the legacy `client.queryRecords(slug, opts)`
|
|
953
|
+
* form. New code should use a canonical `QueryDefinition` (`POST /records/query`)
|
|
954
|
+
* via `client.records.query()` or the canonical `client.queryRecords(resource, definition)`
|
|
955
|
+
* overload — same engine, but boolean trees, `select`, `text`, and `include`
|
|
956
|
+
* become first-class. The GET adapter and this type stay supported during
|
|
957
|
+
* the deprecation window per `docs/maintainers/overview/query-foundation.md`.
|
|
958
|
+
*
|
|
887
959
|
* @example
|
|
888
960
|
* // Top-level filters with bracket notation
|
|
889
961
|
* { 'data.status': 'active', 'data.age[gte]': 18, sort: '-createdAt' }
|
|
@@ -1430,8 +1502,14 @@ export interface PaginatedResponse<T> {
|
|
|
1430
1502
|
}
|
|
1431
1503
|
|
|
1432
1504
|
// =====================================================
|
|
1433
|
-
// Smart Query Types
|
|
1505
|
+
// Smart Query Types (saved-query surface for `client.savedQueries`)
|
|
1434
1506
|
// =====================================================
|
|
1507
|
+
//
|
|
1508
|
+
// These types describe the **stored** saved-query shape and the operator
|
|
1509
|
+
// vocabulary the `/saved-queries/*` routes accept. They back both
|
|
1510
|
+
// `client.savedQueries.*` (canonical) and the deprecated `client.smartQueries`
|
|
1511
|
+
// alias. The SDK still exports the type names with `SmartQuery` prefixes for
|
|
1512
|
+
// back-compat; canonical `SavedQuery*` aliases will be added in a follow-up.
|
|
1435
1513
|
|
|
1436
1514
|
/**
|
|
1437
1515
|
* Smart query definition stored in the database.
|
|
@@ -2882,32 +2960,36 @@ export function getEndpointApiPath(workspaceId: string, path: string): string {
|
|
|
2882
2960
|
}
|
|
2883
2961
|
|
|
2884
2962
|
/**
|
|
2885
|
-
* Generate
|
|
2963
|
+
* Generate Saved Queries base API URL PATH for workspace-level operations.
|
|
2964
|
+
*
|
|
2965
|
+
* Phase 4 (CEN-1198) of the query foundation moved the canonical mount from
|
|
2966
|
+
* `/smart-queries` to `/saved-queries`. The data service dual-mounts both for
|
|
2967
|
+
* the deprecation window; this helper emits the canonical path.
|
|
2886
2968
|
*/
|
|
2887
2969
|
export function getSmartQueriesApiPath(workspaceId: string): string {
|
|
2888
|
-
return `data/workspace/${workspaceId}/api/v1/
|
|
2970
|
+
return `data/workspace/${workspaceId}/api/v1/saved-queries`;
|
|
2889
2971
|
}
|
|
2890
2972
|
|
|
2891
2973
|
/**
|
|
2892
|
-
* Generate
|
|
2974
|
+
* Generate Saved Queries API URL PATH for structure-level operations.
|
|
2893
2975
|
*/
|
|
2894
2976
|
export function getSmartQueriesStructureApiPath(workspaceId: string, structureSlug: string, queryId?: string): string {
|
|
2895
|
-
const basePath = `data/workspace/${workspaceId}/api/v1/
|
|
2977
|
+
const basePath = `data/workspace/${workspaceId}/api/v1/saved-queries/slug/${structureSlug}`;
|
|
2896
2978
|
return queryId ? `${basePath}/${queryId}` : basePath;
|
|
2897
2979
|
}
|
|
2898
2980
|
|
|
2899
2981
|
/**
|
|
2900
|
-
* Generate
|
|
2982
|
+
* Generate Saved Query by name API URL PATH.
|
|
2901
2983
|
*/
|
|
2902
2984
|
export function getSmartQueryByNameApiPath(workspaceId: string, structureSlug: string, name: string): string {
|
|
2903
|
-
return `data/workspace/${workspaceId}/api/v1/
|
|
2985
|
+
return `data/workspace/${workspaceId}/api/v1/saved-queries/slug/${structureSlug}/name/${encodeURIComponent(name)}`;
|
|
2904
2986
|
}
|
|
2905
2987
|
|
|
2906
2988
|
/**
|
|
2907
|
-
* Generate
|
|
2989
|
+
* Generate Saved Query execute API URL PATH.
|
|
2908
2990
|
*/
|
|
2909
2991
|
export function getSmartQueryExecuteApiPath(workspaceId: string, structureSlug: string, queryId: string): string {
|
|
2910
|
-
return `data/workspace/${workspaceId}/api/v1/
|
|
2992
|
+
return `data/workspace/${workspaceId}/api/v1/saved-queries/slug/${structureSlug}/execute/${queryId}`;
|
|
2911
2993
|
}
|
|
2912
2994
|
|
|
2913
2995
|
/**
|
|
@@ -3087,10 +3169,10 @@ export function getComputeJobStatusApiPath(workspaceId: string, jobId: string):
|
|
|
3087
3169
|
// =====================================================
|
|
3088
3170
|
|
|
3089
3171
|
/**
|
|
3090
|
-
* Generate
|
|
3172
|
+
* Generate Saved Query test execution API URL PATH.
|
|
3091
3173
|
*/
|
|
3092
3174
|
export function getSmartQueryTestApiPath(workspaceId: string, structureSlug: string): string {
|
|
3093
|
-
return `data/workspace/${workspaceId}/api/v1/
|
|
3175
|
+
return `data/workspace/${workspaceId}/api/v1/saved-queries/slug/${structureSlug}/test`;
|
|
3094
3176
|
}
|
|
3095
3177
|
|
|
3096
3178
|
// =====================================================
|
|
@@ -3877,26 +3959,189 @@ export class TriggersManager {
|
|
|
3877
3959
|
}
|
|
3878
3960
|
}
|
|
3879
3961
|
|
|
3962
|
+
// =====================================================
|
|
3963
|
+
// Records Manager (canonical query surface — CEN-1194)
|
|
3964
|
+
// =====================================================
|
|
3965
|
+
|
|
3966
|
+
/**
|
|
3967
|
+
* RecordsManager exposes the canonical query surface for records.
|
|
3968
|
+
*
|
|
3969
|
+
* All three methods compile to a single canonical `QueryDefinition` server-side
|
|
3970
|
+
* and return the canonical `{ data, meta }` envelope (`QueryResult<T>`).
|
|
3971
|
+
*
|
|
3972
|
+
* - {@link RecordsManager.query | query} — full POST `/records/query`. Use for
|
|
3973
|
+
* nested boolean trees, `select`, `text`, `include`.
|
|
3974
|
+
* - {@link RecordsManager.list | list} — GET adapter for simple URL-param
|
|
3975
|
+
* queries. Bookmarkable, cacheable, but cannot express nested `or`/`not`.
|
|
3976
|
+
* - {@link RecordsManager.search | search} — sugar over `query({ text: ... })`.
|
|
3977
|
+
*
|
|
3978
|
+
* Access via `client.records`.
|
|
3979
|
+
*
|
|
3980
|
+
* @example
|
|
3981
|
+
* ```ts
|
|
3982
|
+
* // Canonical query — boolean tree, select, paging
|
|
3983
|
+
* const open = await client.records.query<Order>('orders', {
|
|
3984
|
+
* resource: 'orders',
|
|
3985
|
+
* where: {
|
|
3986
|
+
* and: [
|
|
3987
|
+
* { 'data.status': { eq: 'open' } },
|
|
3988
|
+
* { or: [
|
|
3989
|
+
* { 'data.amount': { gte: 100 } },
|
|
3990
|
+
* { 'data.priority': { eq: 'high' } }
|
|
3991
|
+
* ]}
|
|
3992
|
+
* ]
|
|
3993
|
+
* },
|
|
3994
|
+
* sort: [{ field: 'createdAt', direction: 'desc' }],
|
|
3995
|
+
* page: { limit: 50 },
|
|
3996
|
+
* select: { fields: ['id', 'data.status', 'data.amount'] }
|
|
3997
|
+
* });
|
|
3998
|
+
* console.log(open.data, open.meta.hasMore);
|
|
3999
|
+
*
|
|
4000
|
+
* // GET adapter — simple cases
|
|
4001
|
+
* const recent = await client.records.list<Order>('orders', {
|
|
4002
|
+
* 'data.status': 'paid',
|
|
4003
|
+
* sort: '-createdAt',
|
|
4004
|
+
* pageSize: 25,
|
|
4005
|
+
* });
|
|
4006
|
+
*
|
|
4007
|
+
* // Text search — sugar over { text }
|
|
4008
|
+
* const matches = await client.records.search<Order>('orders', 'urgent shipping');
|
|
4009
|
+
* ```
|
|
4010
|
+
*/
|
|
4011
|
+
export class RecordsManager {
|
|
4012
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
4013
|
+
private workspaceId: string;
|
|
4014
|
+
|
|
4015
|
+
constructor(
|
|
4016
|
+
workspaceId: string,
|
|
4017
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
4018
|
+
) {
|
|
4019
|
+
this.workspaceId = workspaceId;
|
|
4020
|
+
this.requestFn = requestFn;
|
|
4021
|
+
}
|
|
4022
|
+
|
|
4023
|
+
/**
|
|
4024
|
+
* Run a canonical query against `POST /records/query`.
|
|
4025
|
+
*
|
|
4026
|
+
* The body **is** a `QueryDefinition`. Returns the canonical `{ data, meta }`
|
|
4027
|
+
* envelope. If `definition.resource` is omitted, `resource` is filled in
|
|
4028
|
+
* from the first argument so the wire shape always matches the contract.
|
|
4029
|
+
*
|
|
4030
|
+
* @example
|
|
4031
|
+
* const open = await client.records.query<Order>('orders', {
|
|
4032
|
+
* resource: 'orders',
|
|
4033
|
+
* where: { 'data.status': { eq: 'open' } },
|
|
4034
|
+
* page: { limit: 100 }
|
|
4035
|
+
* });
|
|
4036
|
+
*/
|
|
4037
|
+
public async query<T = any>(
|
|
4038
|
+
resource: string,
|
|
4039
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
4040
|
+
): Promise<QueryResult<T>> {
|
|
4041
|
+
const path = `data/workspace/${this.workspaceId}/api/v1/records/query`;
|
|
4042
|
+
const body: QueryDefinition = { ...definition, resource: definition.resource ?? resource };
|
|
4043
|
+
const resp = await this.requestFn<T[]>('POST', path, body);
|
|
4044
|
+
// POST /records/query returns canonical `{ data, meta }`. The SDK's
|
|
4045
|
+
// `request()` normalizer leaves objects with a `data` key untouched, so
|
|
4046
|
+
// the runtime shape already matches `QueryResult<T>` — we only need to
|
|
4047
|
+
// re-type the response. `meta` is server-guaranteed for this route.
|
|
4048
|
+
return resp as unknown as QueryResult<T>;
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
/**
|
|
4052
|
+
* Authoring-time dry-run of a canonical query against `POST /records/query/test`.
|
|
4053
|
+
*
|
|
4054
|
+
* Same input shape as {@link RecordsManager.query | query}. Returns
|
|
4055
|
+
* `422 unreadable_field` on fields the caller can't see (instead of the
|
|
4056
|
+
* runtime privacy-preserving empty-result behavior). Use from query
|
|
4057
|
+
* builders to surface precise errors to the author.
|
|
4058
|
+
*/
|
|
4059
|
+
public async test<T = any>(
|
|
4060
|
+
resource: string,
|
|
4061
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
4062
|
+
): Promise<QueryResult<T>> {
|
|
4063
|
+
const path = `data/workspace/${this.workspaceId}/api/v1/records/query/test`;
|
|
4064
|
+
const body: QueryDefinition = { ...definition, resource: definition.resource ?? resource };
|
|
4065
|
+
const resp = await this.requestFn<T[]>('POST', path, body);
|
|
4066
|
+
return resp as unknown as QueryResult<T>;
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
/**
|
|
4070
|
+
* GET adapter for simple, URL-encodable queries (`?status=paid&sort=-createdAt`).
|
|
4071
|
+
*
|
|
4072
|
+
* Server-side this routes through the same canonical engine as
|
|
4073
|
+
* {@link RecordsManager.query | query} (per CEN-1181 WS3) — the URL
|
|
4074
|
+
* params compile into a `QueryDefinition` before execution. Use this when
|
|
4075
|
+
* a flat AND of field conditions is enough; reach for `query()` when you
|
|
4076
|
+
* need nested booleans, `select`, `text`, or `include`.
|
|
4077
|
+
*
|
|
4078
|
+
* Returns the records-list `ApiResponse<T[]>` envelope unchanged so
|
|
4079
|
+
* callers that read `meta.page` / `meta.pageSize` keep working during
|
|
4080
|
+
* the deprecation window.
|
|
4081
|
+
*/
|
|
4082
|
+
public list<T = any>(
|
|
4083
|
+
resource: string,
|
|
4084
|
+
urlOpts?: QueryRecordOptions
|
|
4085
|
+
): Promise<ApiResponse<T[]>> {
|
|
4086
|
+
const path = getRecordApiPath(this.workspaceId, resource);
|
|
4087
|
+
return this.requestFn<T[]>('GET', path, null, urlOpts);
|
|
4088
|
+
}
|
|
4089
|
+
|
|
4090
|
+
/**
|
|
4091
|
+
* Full-text search sugar — equivalent to `query(resource, { text: ... })`.
|
|
4092
|
+
*
|
|
4093
|
+
* Routes through `RecordsSearchExecutor` (Meilisearch) when only `text` is
|
|
4094
|
+
* provided, or through the hybrid Meili-first path when `where` is also
|
|
4095
|
+
* set. Result envelope is identical across pure-filter, pure-text, and
|
|
4096
|
+
* hybrid (`{ data, meta }`).
|
|
4097
|
+
*/
|
|
4098
|
+
public async search<T = any>(
|
|
4099
|
+
resource: string,
|
|
4100
|
+
text: string,
|
|
4101
|
+
opts?: {
|
|
4102
|
+
fields?: string[];
|
|
4103
|
+
typoTolerance?: boolean;
|
|
4104
|
+
where?: WhereExpression;
|
|
4105
|
+
sort?: SortClause[];
|
|
4106
|
+
page?: PageClause;
|
|
4107
|
+
select?: SelectClause;
|
|
4108
|
+
}
|
|
4109
|
+
): Promise<QueryResult<T>> {
|
|
4110
|
+
return this.query<T>(resource, {
|
|
4111
|
+
resource,
|
|
4112
|
+
text: { query: text, fields: opts?.fields, typoTolerance: opts?.typoTolerance },
|
|
4113
|
+
where: opts?.where,
|
|
4114
|
+
sort: opts?.sort,
|
|
4115
|
+
page: opts?.page,
|
|
4116
|
+
select: opts?.select,
|
|
4117
|
+
});
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
|
|
3880
4121
|
// =====================================================
|
|
3881
4122
|
// Smart Queries Manager
|
|
3882
4123
|
// =====================================================
|
|
3883
4124
|
|
|
3884
4125
|
/**
|
|
3885
|
-
* SmartQueriesManager
|
|
3886
|
-
*
|
|
3887
|
-
*
|
|
3888
|
-
*
|
|
4126
|
+
* SmartQueriesManager — reusable, parameterized saved queries. Access via
|
|
4127
|
+
* `client.savedQueries` (canonical) or `client.smartQueries` (deprecated alias).
|
|
4128
|
+
*
|
|
4129
|
+
* Phase 4 of the query foundation (CEN-1198) shipped the canonical
|
|
4130
|
+
* `/saved-queries/*` HTTP routes; this manager now routes through them. The
|
|
4131
|
+
* data service dual-mounts the deprecated `/smart-queries/*` alias for the
|
|
4132
|
+
* deprecation window. New code that doesn't need saved queries should still
|
|
4133
|
+
* prefer `client.records.query()` for ad-hoc queries.
|
|
3889
4134
|
*
|
|
3890
4135
|
* Usage:
|
|
3891
4136
|
* ```ts
|
|
3892
|
-
* // List
|
|
3893
|
-
* const queries = await client.
|
|
4137
|
+
* // List saved queries for a structure
|
|
4138
|
+
* const queries = await client.savedQueries.list('employee');
|
|
3894
4139
|
*
|
|
3895
|
-
* // Execute a
|
|
3896
|
-
* const results = await client.
|
|
4140
|
+
* // Execute a saved query by ID
|
|
4141
|
+
* const results = await client.savedQueries.execute('employee', 'query-uuid');
|
|
3897
4142
|
*
|
|
3898
|
-
* // Get a
|
|
3899
|
-
* const query = await client.
|
|
4143
|
+
* // Get a saved query by name
|
|
4144
|
+
* const query = await client.savedQueries.getByName('employee', 'Active Employees');
|
|
3900
4145
|
* ```
|
|
3901
4146
|
*/
|
|
3902
4147
|
export class SmartQueriesManager {
|
|
@@ -5513,7 +5758,9 @@ export class CentraliSDK {
|
|
|
5513
5758
|
private options: CentraliSDKOptions;
|
|
5514
5759
|
private _realtime: RealtimeManager | null = null;
|
|
5515
5760
|
private _triggers: TriggersManager | null = null;
|
|
5761
|
+
private _records: RecordsManager | null = null;
|
|
5516
5762
|
private _smartQueries: SmartQueriesManager | null = null;
|
|
5763
|
+
private _queryRecordsLegacyWarned: boolean = false;
|
|
5517
5764
|
private _anomalyInsights: AnomalyInsightsManager | null = null;
|
|
5518
5765
|
private _validation: ValidationManager | null = null;
|
|
5519
5766
|
private _orchestrations: OrchestrationsManager | null = null;
|
|
@@ -5737,25 +5984,75 @@ export class CentraliSDK {
|
|
|
5737
5984
|
}
|
|
5738
5985
|
|
|
5739
5986
|
/**
|
|
5740
|
-
*
|
|
5987
|
+
* Records namespace — canonical query surface for records (CEN-1194).
|
|
5988
|
+
*
|
|
5989
|
+
* Three methods, one engine, one envelope:
|
|
5990
|
+
* - `records.query(resource, definition)` — POST `/records/query` with a
|
|
5991
|
+
* full `QueryDefinition` (boolean trees, `select`, `text`, `include`).
|
|
5992
|
+
* - `records.list(resource, urlOpts?)` — GET adapter for simple URL-param
|
|
5993
|
+
* queries. Bookmarkable; cannot express nested booleans.
|
|
5994
|
+
* - `records.search(resource, text, opts?)` — sugar over `query({ text })`.
|
|
5995
|
+
*
|
|
5996
|
+
* @example
|
|
5997
|
+
* ```ts
|
|
5998
|
+
* // Boolean tree with sort + projection
|
|
5999
|
+
* const orders = await client.records.query<Order>('orders', {
|
|
6000
|
+
* resource: 'orders',
|
|
6001
|
+
* where: {
|
|
6002
|
+
* and: [
|
|
6003
|
+
* { 'data.status': { eq: 'paid' } },
|
|
6004
|
+
* { 'data.amount': { gte: 100 } }
|
|
6005
|
+
* ]
|
|
6006
|
+
* },
|
|
6007
|
+
* sort: [{ field: 'createdAt', direction: 'desc' }],
|
|
6008
|
+
* page: { limit: 50 },
|
|
6009
|
+
* select: { fields: ['id', 'data.amount', 'data.customer'] }
|
|
6010
|
+
* });
|
|
6011
|
+
*
|
|
6012
|
+
* // Simple GET
|
|
6013
|
+
* const recent = await client.records.list<Order>('orders', {
|
|
6014
|
+
* 'data.status': 'paid',
|
|
6015
|
+
* sort: '-createdAt',
|
|
6016
|
+
* });
|
|
6017
|
+
*
|
|
6018
|
+
* // Text search
|
|
6019
|
+
* const matches = await client.records.search<Order>('orders', 'urgent');
|
|
6020
|
+
* ```
|
|
6021
|
+
*/
|
|
6022
|
+
public get records(): RecordsManager {
|
|
6023
|
+
if (!this._records) {
|
|
6024
|
+
this._records = new RecordsManager(
|
|
6025
|
+
this.options.workspaceId,
|
|
6026
|
+
this.request.bind(this)
|
|
6027
|
+
);
|
|
6028
|
+
}
|
|
6029
|
+
return this._records;
|
|
6030
|
+
}
|
|
6031
|
+
|
|
6032
|
+
/**
|
|
6033
|
+
* Saved Queries namespace — list, execute, create, update, and delete
|
|
6034
|
+
* saved (formerly "smart") queries. Routes through the canonical
|
|
6035
|
+
* `/saved-queries/*` endpoints (Phase 4 of the query foundation,
|
|
6036
|
+
* CEN-1198). The data service dual-mounts the deprecated `/smart-queries`
|
|
6037
|
+
* alias for the deprecation window.
|
|
5741
6038
|
*
|
|
5742
6039
|
* Usage:
|
|
5743
6040
|
* ```ts
|
|
5744
|
-
* // List all
|
|
5745
|
-
* const allQueries = await client.
|
|
6041
|
+
* // List all saved queries in workspace
|
|
6042
|
+
* const allQueries = await client.savedQueries.listAll();
|
|
5746
6043
|
*
|
|
5747
|
-
* // List
|
|
5748
|
-
* const queries = await client.
|
|
6044
|
+
* // List saved queries for a structure
|
|
6045
|
+
* const queries = await client.savedQueries.list('employee');
|
|
5749
6046
|
*
|
|
5750
|
-
* // Get a
|
|
5751
|
-
* const query = await client.
|
|
6047
|
+
* // Get a saved query by name
|
|
6048
|
+
* const query = await client.savedQueries.getByName('employee', 'Active Employees');
|
|
5752
6049
|
*
|
|
5753
|
-
* // Execute a
|
|
5754
|
-
* const results = await client.
|
|
6050
|
+
* // Execute a saved query
|
|
6051
|
+
* const results = await client.savedQueries.execute('employee', query.data.id);
|
|
5755
6052
|
* console.log('Found:', results.data.length, 'records');
|
|
5756
6053
|
* ```
|
|
5757
6054
|
*/
|
|
5758
|
-
public get
|
|
6055
|
+
public get savedQueries(): SmartQueriesManager {
|
|
5759
6056
|
if (!this._smartQueries) {
|
|
5760
6057
|
this._smartQueries = new SmartQueriesManager(
|
|
5761
6058
|
this.options.workspaceId,
|
|
@@ -5765,6 +6062,17 @@ export class CentraliSDK {
|
|
|
5765
6062
|
return this._smartQueries;
|
|
5766
6063
|
}
|
|
5767
6064
|
|
|
6065
|
+
/**
|
|
6066
|
+
* @deprecated Use `client.savedQueries` instead. The "smart queries"
|
|
6067
|
+
* surface was renamed to "saved queries" in Phase 4 of the query
|
|
6068
|
+
* foundation (CEN-1198). This getter is a deprecated alias and will be
|
|
6069
|
+
* removed in a future major SDK release.
|
|
6070
|
+
*/
|
|
6071
|
+
public get smartQueries(): SmartQueriesManager {
|
|
6072
|
+
emitDeprecationWarning('client.smartQueries is deprecated. Use client.savedQueries instead.');
|
|
6073
|
+
return this.savedQueries;
|
|
6074
|
+
}
|
|
6075
|
+
|
|
5768
6076
|
/**
|
|
5769
6077
|
* Anomaly Insights namespace for querying and managing AI-generated insights.
|
|
5770
6078
|
*
|
|
@@ -6210,12 +6518,54 @@ export class CentraliSDK {
|
|
|
6210
6518
|
* pageSize: 100
|
|
6211
6519
|
* });
|
|
6212
6520
|
*/
|
|
6521
|
+
/**
|
|
6522
|
+
* Canonical query (CEN-1194). When called with a `QueryDefinition` body,
|
|
6523
|
+
* routes to `POST /records/query` and returns canonical `QueryResult<T>`.
|
|
6524
|
+
*
|
|
6525
|
+
* @example
|
|
6526
|
+
* const result = await centrali.queryRecords<Order>('orders', {
|
|
6527
|
+
* resource: 'orders',
|
|
6528
|
+
* where: { 'data.status': { eq: 'paid' } },
|
|
6529
|
+
* page: { limit: 50 }
|
|
6530
|
+
* });
|
|
6531
|
+
* console.log(result.data, result.meta.hasMore);
|
|
6532
|
+
*/
|
|
6533
|
+
public queryRecords<T = any>(
|
|
6534
|
+
resource: string,
|
|
6535
|
+
definition: QueryDefinition
|
|
6536
|
+
): Promise<QueryResult<T>>;
|
|
6537
|
+
/**
|
|
6538
|
+
* Legacy GET-adapter form. Pass `QueryRecordOptions` (URL-param style with
|
|
6539
|
+
* `data.field[op]` keys, `sort: '-createdAt'`, `pageSize`, etc.) and the
|
|
6540
|
+
* call routes to `GET /records/slug/:rs`.
|
|
6541
|
+
*
|
|
6542
|
+
* @deprecated Since 5.5.0. Prefer the canonical overload above (pass a
|
|
6543
|
+
* `QueryDefinition`) or {@link CentraliSDK.records | client.records.list()}
|
|
6544
|
+
* for the GET adapter explicitly. The legacy form keeps working — server-side
|
|
6545
|
+
* it already routes through the canonical engine (CEN-1181 WS3) — but the
|
|
6546
|
+
* client-side type story diverges from the canonical surface. Emits a
|
|
6547
|
+
* one-shot `console.warn` per client.
|
|
6548
|
+
*/
|
|
6213
6549
|
public queryRecords<T = any>(
|
|
6214
6550
|
recordSlug: string,
|
|
6215
6551
|
queryParams?: QueryRecordOptions
|
|
6216
|
-
): Promise<ApiResponse<T
|
|
6217
|
-
|
|
6218
|
-
|
|
6552
|
+
): Promise<ApiResponse<T>>;
|
|
6553
|
+
public queryRecords<T = any>(
|
|
6554
|
+
resourceOrSlug: string,
|
|
6555
|
+
arg2?: QueryDefinition | QueryRecordOptions
|
|
6556
|
+
): Promise<QueryResult<T>> | Promise<ApiResponse<T>> {
|
|
6557
|
+
if (isCanonicalQueryDefinition(arg2)) {
|
|
6558
|
+
return this.records.query<T>(resourceOrSlug, arg2);
|
|
6559
|
+
}
|
|
6560
|
+
if (!this._queryRecordsLegacyWarned) {
|
|
6561
|
+
this._queryRecordsLegacyWarned = true;
|
|
6562
|
+
// eslint-disable-next-line no-console
|
|
6563
|
+
console.warn(
|
|
6564
|
+
'[centrali-sdk] `client.queryRecords(slug, urlOpts)` (legacy URL-param form) is deprecated — pass a canonical `QueryDefinition` (`{ resource, where, sort, page, … }`) for `POST /records/query`, or use `client.records.list(resource, urlOpts)` for the GET adapter explicitly.'
|
|
6565
|
+
);
|
|
6566
|
+
}
|
|
6567
|
+
const path = getRecordApiPath(this.options.workspaceId, resourceOrSlug);
|
|
6568
|
+
return this.request<T>('GET', path, null, arg2);
|
|
6219
6569
|
}
|
|
6220
6570
|
|
|
6221
6571
|
/** Get records by Ids. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centrali-io/centrali-sdk",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "Centrali Node SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"url": "git+https://github.com/blueinit/centrali-sdk.git"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
+
"sync:query-types": "node scripts/sync-query-types.mjs",
|
|
14
|
+
"prebuild": "npm run sync:query-types",
|
|
13
15
|
"build": "tsc --project tsconfig.json",
|
|
14
16
|
"prepublishOnly": "npm run build"
|
|
15
17
|
},
|