diff --git a/.changeset/polite-buckets-raise.md b/.changeset/polite-buckets-raise.md new file mode 100644 index 0000000000..cb2ab8c40c --- /dev/null +++ b/.changeset/polite-buckets-raise.md @@ -0,0 +1,5 @@ +--- +"@directus/sdk": patch +--- + +Added missing filter operators, removed the reliance on `@directus/types`, fixed content-type regression on graphql diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a355c57a2f..e7b4176bac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1833,10 +1833,6 @@ importers: version: 0.31.1(happy-dom@9.18.3)(sass@1.62.1) sdk: - dependencies: - '@directus/types': - specifier: workspace:* - version: link:../packages/types devDependencies: '@directus/tsconfig': specifier: workspace:* diff --git a/sdk/package.json b/sdk/package.json index eadee1e4d0..7687899288 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -54,9 +54,6 @@ "typescript": "5.0.4", "vitest": "0.31.1" }, - "dependencies": { - "@directus/types": "workspace:*" - }, "engines": { "node": ">=18.0.0" } diff --git a/sdk/src/graphql/composable.ts b/sdk/src/graphql/composable.ts index 199e8efe9b..f992351fd9 100644 --- a/sdk/src/graphql/composable.ts +++ b/sdk/src/graphql/composable.ts @@ -20,18 +20,23 @@ export const graphql = () => { const options: RequestInit = { method: 'POST', body: JSON.stringify({ query, variables }), - headers: {}, }; + const headers: Record = {}; + if ('getToken' in this) { const token = await (this.getToken as AuthenticationClient['getToken'])(); if (token) { - if (!options.headers) options.headers = {}; - options.headers = { Authorization: `Bearer ${token}` }; + headers['Authorization'] = `Bearer ${token}`; } } + if ('Content-Type' in headers === false) { + headers['Content-Type'] = 'application/json'; + } + + options.headers = headers; const requestPath = scope === 'items' ? '/graphql' : '/graphql/system'; const requestUrl = getRequestUrl(client.url, requestPath); diff --git a/sdk/src/realtime/types.ts b/sdk/src/realtime/types.ts index ea308e9fef..e2d8b6ad44 100644 --- a/sdk/src/realtime/types.ts +++ b/sdk/src/realtime/types.ts @@ -1,4 +1,3 @@ -import type { PrimaryKey } from '@directus/types'; import type { Query } from '../types/query.js'; import type { ApplyQueryFields, CollectionType } from '../index.js'; @@ -73,5 +72,5 @@ export type SubscriptionPayload = { init: Item[]; create: Item[]; update: Item[]; - delete: PrimaryKey[]; + delete: string[] | number[]; }; diff --git a/sdk/src/rest/commands/delete/items.ts b/sdk/src/rest/commands/delete/items.ts index ed0f0d42ed..732f2781e6 100644 --- a/sdk/src/rest/commands/delete/items.ts +++ b/sdk/src/rest/commands/delete/items.ts @@ -1,4 +1,3 @@ -import type { PrimaryKey } from '@directus/types'; import type { Query } from '../../../types/index.js'; import type { RestCommand } from '../../types.js'; @@ -13,7 +12,7 @@ import type { RestCommand } from '../../types.js'; export const deleteItems = >( collection: Collection, - keysOrQuery: PrimaryKey[] | TQuery + keysOrQuery: string[] | number[] | TQuery ): RestCommand => () => { const _collection = String(collection); @@ -39,7 +38,7 @@ export const deleteItems = export const deleteItem = ( collection: Collection, - key: PrimaryKey + key: string | number ): RestCommand => () => { const _collection = String(collection); diff --git a/sdk/src/rest/commands/read/items.ts b/sdk/src/rest/commands/read/items.ts index dfb44de7fc..cf2cf270e1 100644 --- a/sdk/src/rest/commands/read/items.ts +++ b/sdk/src/rest/commands/read/items.ts @@ -1,4 +1,3 @@ -import type { PrimaryKey } from '@directus/types'; import type { ApplyQueryFields, CollectionType, Query, RegularCollections } from '../../../types/index.js'; import type { RestCommand } from '../../types.js'; @@ -55,7 +54,7 @@ export const readItem = const TQuery extends Query> >( collection: Collection, - key: PrimaryKey, + key: string | number, query?: TQuery ): RestCommand, Schema> => () => { diff --git a/sdk/src/rest/commands/update/items.ts b/sdk/src/rest/commands/update/items.ts index 2c67a5c0be..36f1a40104 100644 --- a/sdk/src/rest/commands/update/items.ts +++ b/sdk/src/rest/commands/update/items.ts @@ -1,4 +1,3 @@ -import type { PrimaryKey } from '@directus/types'; import type { ApplyQueryFields, CollectionType, Query, UnpackList } from '../../../types/index.js'; import type { RestCommand } from '../../types.js'; @@ -21,7 +20,7 @@ export type UpdateItemOutput< export const updateItems = >( collection: Collection, - keys: PrimaryKey[], + keys: string[] | number[], item: Partial>, query?: TQuery ): RestCommand[], Schema> => @@ -54,7 +53,7 @@ export const updateItem = Item = UnpackList >( collection: Collection, - key: PrimaryKey, + key: string | number, item: Partial, query?: TQuery ): RestCommand, Schema> => diff --git a/sdk/src/types/deep.ts b/sdk/src/types/deep.ts new file mode 100644 index 0000000000..256144cf78 --- /dev/null +++ b/sdk/src/types/deep.ts @@ -0,0 +1,27 @@ +import type { MergeObjects, Query } from './query.js'; +import type { ItemType, RelationalFields } from './schema.js'; +import type { UnpackList } from './utils.js'; + +/** + * Deep filter object + */ +export type QueryDeep = UnpackList extends infer FlatItem + ? RelationalFields extends never + ? never + : { + [Field in RelationalFields as ExtractCollection extends any[] + ? Field + : never]?: ExtractCollection extends infer CollectionItem + ? Query extends infer TQuery + ? MergeObjects< + QueryDeep, + { + [Key in keyof Omit as `_${string & Key}`]: TQuery[Key]; + } + > + : never + : never; + } + : never; + +type ExtractCollection = Extract>; diff --git a/sdk/src/types/filters.ts b/sdk/src/types/filters.ts new file mode 100644 index 0000000000..511f6c9b47 --- /dev/null +++ b/sdk/src/types/filters.ts @@ -0,0 +1,79 @@ +import type { RelationalFields } from './schema.js'; +import type { UnpackList } from './utils.js'; + +/** + * Filters + */ +export type QueryFilter = WrapLogicalFilters>; + +/** + * Query filters without logical filters + */ +export type NestedQueryFilter = UnpackList extends infer FlatItem + ? { + [Field in keyof FlatItem]?: + | (Field extends RelationalFields + ? WrapRelationalFilters> + : never) + | FilterOperators; + } + : never; + +/** + * All regular filter operators + * + * TODO would love to filter this based on field type but thats not accurate enough in the schema atm + */ +export type FilterOperators = { + _eq?: T; + _neq?: T; + _gt?: T; + _gte?: T; + _lt?: T; + _lte?: T; + _in?: T[]; + _nin?: T[]; + _between?: [T, T]; + _nbetween?: [T, T]; + _contains?: T; + _ncontains?: T; + _starts_with?: T; + _istarts_with?: T; + _nstarts_with?: T; + _nistarts_with?: T; + _ends_with?: T; + _iends_with?: T; + _nends_with?: T; + _niends_with?: T; + _empty?: boolean; + _nempty?: boolean; + _nnull?: boolean; + _null?: boolean; + _intersects?: T; + _nintersects?: T; + _intersects_bbox?: T; + _nintersects_bbox?: T; + _regex?: T; +}; + +/** + * Relational filter operators + */ +export type RelationalFilterOperators = '_some' | '_none'; + +export type WrapRelationalFilters = + | { + [Operator in RelationalFilterOperators]?: Filters; + } + | Filters; + +/** + * Logical filter operations + */ +export type LogicalFilterOperators = '_or' | '_and'; + +export type WrapLogicalFilters = + | { + [Operator in LogicalFilterOperators]?: WrapLogicalFilters[]; + } + | Filters; diff --git a/sdk/src/types/index.ts b/sdk/src/types/index.ts index 528fd754c0..8daeafe7d7 100644 --- a/sdk/src/types/index.ts +++ b/sdk/src/types/index.ts @@ -1,6 +1,8 @@ export * from './aggregate.js'; export * from './client.js'; +export * from './deep.js'; export * from './fields.js'; +export * from './filters.js'; export * from './output.js'; export * from './query.js'; export * from './request.js'; diff --git a/sdk/src/types/query.ts b/sdk/src/types/query.ts index c10451b5ae..018256a9e3 100644 --- a/sdk/src/types/query.ts +++ b/sdk/src/types/query.ts @@ -1,5 +1,7 @@ +import type { QueryDeep } from './deep.js'; import type { HasNestedFields, QueryFields } from './fields.js'; -import type { ItemType, RelationalFields } from './schema.js'; +import type { QueryFilter } from './filters.js'; +import type { ItemType } from './schema.js'; import type { IfAny, UnpackList } from './utils.js'; /** @@ -45,52 +47,6 @@ export type MergeFields = HasNestedFields extends never ? Extract, string> : Extract, string> | MergeRelationalFields; -/** - * Filters - */ -export type QueryFilter = UnpackList extends infer FlatItem - ? { - [Field in keyof FlatItem]?: - | (Field extends RelationalFields ? QueryFilter : never) - | FilterOperatorsByType; - } - : never; - -/** - * All available filter operators - * TODO would love to filter this based on field type but thats not accurate enough in the schema atm - */ -export type FilterOperatorsByType = { - _eq?: T; - _neq?: T; - _gt?: T; - _gte?: T; - _lt?: T; - _lte?: T; - _in?: T[]; - _nin?: T[]; - _between?: [T, T]; - _nbetween?: [T, T]; - _contains?: T; - _ncontains?: T; - _starts_with?: T; - _istarts_with?: T; - _nstarts_with?: T; - _nistarts_with?: T; - _ends_with?: T; - _iends_with?: T; - _nends_with?: T; - _niends_with?: T; - _empty?: boolean; - _nempty?: boolean; - _nnull?: boolean; - _null?: boolean; - _intersects?: T; - _nintersects?: T; - _intersects_bbox?: T; - _nintersects_bbox?: T; -}; - /** * Query sort * TODO expand to relational sorting (same object notation as fields i guess) @@ -101,24 +57,6 @@ export type QuerySort<_Schema extends object, Item> = UnpackList extends i }[keyof FlatItem] : never; -/** - * Deep filter object - */ -export type QueryDeep = UnpackList extends infer FlatItem - ? RelationalFields extends never - ? never - : { - [Field in RelationalFields]?: Query extends infer TQuery - ? MergeObjects< - QueryDeep, - { - [Key in keyof Omit as `_${string & Key}`]: TQuery[Key]; - } - > - : never; - } - : never; - export type MergeObjects = A extends object ? A & B : never; /**