@strapi/strapi 4.13.0-beta.0 → 4.13.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/README.md +13 -5
- package/lib/Strapi.js +11 -0
- package/lib/commands/actions/import/action.js +4 -4
- package/lib/commands/actions/import/command.js +1 -1
- package/lib/commands/actions/transfer/action.js +3 -6
- package/lib/commands/actions/transfer/command.js +1 -1
- package/lib/commands/actions/watch-admin/action.js +1 -1
- package/lib/commands/builders/admin.js +1 -1
- package/lib/commands/utils/data-transfer.js +39 -1
- package/lib/core/loaders/index.js +1 -0
- package/lib/core/loaders/plugins/get-enabled-plugins.js +40 -13
- package/lib/core/loaders/sanitizers.js +1 -1
- package/lib/core/loaders/validators.js +5 -0
- package/lib/core/registries/validators.js +26 -0
- package/lib/core-api/controller/collection-type.js +14 -8
- package/lib/core-api/controller/index.js +15 -3
- package/lib/core-api/controller/single-type.js +2 -0
- package/lib/factories.d.ts +10 -13
- package/lib/factories.js +12 -2
- package/lib/services/entity-service/index.d.ts +1 -100
- package/lib/services/entity-service/index.js +1 -0
- package/lib/services/entity-service/types/index.d.ts +228 -0
- package/lib/services/entity-service/types/params/attributes.d.ts +146 -0
- package/lib/services/entity-service/types/params/data.d.ts +4 -0
- package/lib/services/entity-service/types/params/fields.d.ts +74 -0
- package/lib/services/entity-service/types/params/filters/index.d.ts +75 -0
- package/lib/services/entity-service/types/params/filters/operators.d.ts +30 -0
- package/lib/services/entity-service/types/params/index.d.ts +79 -0
- package/lib/services/entity-service/types/params/pagination.d.ts +13 -0
- package/lib/services/entity-service/types/params/populate.d.ts +130 -0
- package/lib/services/entity-service/types/params/publication-state.d.ts +38 -0
- package/lib/services/entity-service/types/params/search.d.ts +1 -0
- package/lib/services/entity-service/types/params/sort.d.ts +106 -0
- package/lib/services/entity-service/types/plugin.d.ts +11 -0
- package/lib/services/entity-service/types/result.d.ts +205 -0
- package/lib/types/core/attributes/common.d.ts +13 -10
- package/lib/types/core/attributes/component.d.ts +3 -0
- package/lib/types/core/attributes/date-time.d.ts +2 -1
- package/lib/types/core/attributes/dynamic-zone.d.ts +10 -7
- package/lib/types/core/attributes/media.d.ts +8 -0
- package/lib/types/core/attributes/relation.d.ts +69 -28
- package/lib/types/core/attributes/time.d.ts +1 -1
- package/lib/types/core/attributes/timestamp.d.ts +1 -1
- package/lib/types/core/attributes/uid.d.ts +7 -17
- package/lib/types/core/attributes/utils.d.ts +61 -6
- package/lib/types/core/common/index.d.ts +12 -0
- package/lib/types/core/common/uid.d.ts +12 -16
- package/lib/types/core/index.d.ts +1 -0
- package/lib/types/core/plugins/index.d.ts +16 -0
- package/lib/types/core/schemas/index.d.ts +1 -0
- package/lib/types/core/strapi/index.d.ts +7 -2
- package/lib/types/core-api/controller.d.ts +12 -10
- package/lib/types/index.d.ts +2 -0
- package/lib/types/shared/entity-service.d.ts +1 -0
- package/lib/types/shared/index.d.ts +2 -0
- package/lib/types/shared/plugins.d.ts +3 -0
- package/lib/types/utils/expression.d.ts +29 -6
- package/lib/types/utils/guard.d.ts +14 -1
- package/lib/types/utils/index.d.ts +8 -0
- package/lib/types/utils/object.d.ts +35 -1
- package/lib/types/utils/string.d.ts +18 -0
- package/package.json +17 -16
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type { Attribute, Common, Utils } from '@strapi/strapi';
|
|
2
|
+
import type { PartialEntity, Entity, Result, PaginatedResult } from './result';
|
|
3
|
+
|
|
4
|
+
import type * as Params from './params';
|
|
5
|
+
|
|
6
|
+
// TODO: Move params to @strapi/utils (related to convert-query-params)
|
|
7
|
+
export * as Params from './params';
|
|
8
|
+
|
|
9
|
+
export * from './result';
|
|
10
|
+
export * from './plugin';
|
|
11
|
+
|
|
12
|
+
type WrapAction = Omit<keyof EntityService, 'wrapParams' | 'wrapResult' | 'emitEvent'>;
|
|
13
|
+
|
|
14
|
+
export interface EntityService {
|
|
15
|
+
wrapParams<
|
|
16
|
+
TResult = unknown,
|
|
17
|
+
TContentTypeUID extends Common.UID.ContentType = Common.UID.ContentType,
|
|
18
|
+
TParams extends object = object
|
|
19
|
+
>(
|
|
20
|
+
params?: TParams,
|
|
21
|
+
options?: { uid: TContentTypeUID; action: WrapAction }
|
|
22
|
+
): Promise<TResult> | TResult;
|
|
23
|
+
|
|
24
|
+
wrapResult<
|
|
25
|
+
TResult = unknown,
|
|
26
|
+
TContentTypeUID extends Common.UID.ContentType = Common.UID.ContentType
|
|
27
|
+
>(
|
|
28
|
+
result: unknown,
|
|
29
|
+
options?: { uid: TContentTypeUID; action: WrapAction }
|
|
30
|
+
): Promise<TResult> | TResult;
|
|
31
|
+
|
|
32
|
+
emitEvent<TContentTypeUID extends Common.UID.ContentType>(
|
|
33
|
+
uid: TContentTypeUID,
|
|
34
|
+
event: string,
|
|
35
|
+
entity: Entity<TContentTypeUID>
|
|
36
|
+
): Promise<void>;
|
|
37
|
+
// TODO: Split in 2 different signatures for both single types & collection types
|
|
38
|
+
findMany<
|
|
39
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
40
|
+
TParams extends Params.Pick<
|
|
41
|
+
TContentTypeUID,
|
|
42
|
+
| 'fields'
|
|
43
|
+
| 'filters'
|
|
44
|
+
| '_q'
|
|
45
|
+
| 'pagination:offset'
|
|
46
|
+
| 'sort'
|
|
47
|
+
| 'populate'
|
|
48
|
+
| 'publicationState'
|
|
49
|
+
| 'plugin'
|
|
50
|
+
>
|
|
51
|
+
>(
|
|
52
|
+
uid: TContentTypeUID,
|
|
53
|
+
params?: TParams
|
|
54
|
+
): Utils.Expression.MatchFirst<
|
|
55
|
+
[
|
|
56
|
+
[Common.UID.IsCollectionType<TContentTypeUID>, Promise<Result<TContentTypeUID, TParams>[]>],
|
|
57
|
+
[Common.UID.IsSingleType<TContentTypeUID>, Promise<Result<TContentTypeUID, TParams> | null>]
|
|
58
|
+
],
|
|
59
|
+
Promise<(Result<TContentTypeUID, TParams> | null) | Result<TContentTypeUID, TParams>[]>
|
|
60
|
+
>;
|
|
61
|
+
|
|
62
|
+
findOne<
|
|
63
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
64
|
+
TParams extends Params.Pick<TContentTypeUID, 'fields' | 'populate'>
|
|
65
|
+
>(
|
|
66
|
+
uid: TContentTypeUID,
|
|
67
|
+
entityId: Params.Attribute.ID,
|
|
68
|
+
params?: TParams
|
|
69
|
+
): Promise<Result<TContentTypeUID, TParams> | null>;
|
|
70
|
+
|
|
71
|
+
delete<
|
|
72
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
73
|
+
TParams extends Params.Pick<TContentTypeUID, 'fields' | 'populate'>
|
|
74
|
+
>(
|
|
75
|
+
uid: TContentTypeUID,
|
|
76
|
+
entityId: Params.Attribute.ID,
|
|
77
|
+
params?: TParams
|
|
78
|
+
): Promise<Result<TContentTypeUID, TParams> | null>;
|
|
79
|
+
|
|
80
|
+
create<
|
|
81
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
82
|
+
TParams extends Params.Pick<TContentTypeUID, 'data' | 'files' | 'fields' | 'populate'>
|
|
83
|
+
>(
|
|
84
|
+
uid: TContentTypeUID,
|
|
85
|
+
params?: TParams
|
|
86
|
+
): Promise<Result<TContentTypeUID, TParams>>;
|
|
87
|
+
|
|
88
|
+
update<
|
|
89
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
90
|
+
TParams extends Params.Pick<TContentTypeUID, 'data:partial' | 'files' | 'fields' | 'populate'>
|
|
91
|
+
>(
|
|
92
|
+
uid: TContentTypeUID,
|
|
93
|
+
entityId: Params.Attribute.ID,
|
|
94
|
+
params?: TParams
|
|
95
|
+
): Promise<Result<TContentTypeUID, TParams> | null>;
|
|
96
|
+
|
|
97
|
+
findPage<
|
|
98
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
99
|
+
TParams extends Params.Pick<
|
|
100
|
+
TContentTypeUID,
|
|
101
|
+
| 'fields'
|
|
102
|
+
| 'populate'
|
|
103
|
+
| 'pagination'
|
|
104
|
+
| 'sort'
|
|
105
|
+
| 'filters'
|
|
106
|
+
| '_q'
|
|
107
|
+
| 'publicationState'
|
|
108
|
+
| 'plugin'
|
|
109
|
+
>
|
|
110
|
+
>(
|
|
111
|
+
uid: TContentTypeUID,
|
|
112
|
+
params?: TParams
|
|
113
|
+
): Promise<PaginatedResult<TContentTypeUID, TParams>>;
|
|
114
|
+
|
|
115
|
+
clone<
|
|
116
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
117
|
+
TParams extends Params.Pick<TContentTypeUID, 'data' | 'files' | 'fields' | 'populate'>
|
|
118
|
+
>(
|
|
119
|
+
uid: TContentTypeUID,
|
|
120
|
+
cloneId: Params.Attribute.ID,
|
|
121
|
+
params?: TParams
|
|
122
|
+
): Promise<Result<TContentTypeUID, TParams> | null>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @deprecated
|
|
126
|
+
*/
|
|
127
|
+
deleteMany<TContentTypeUID extends Common.UID.ContentType>(
|
|
128
|
+
uid: TContentTypeUID,
|
|
129
|
+
params: Params.Pick<TContentTypeUID, 'filters' | '_q'>
|
|
130
|
+
): Promise<{ count: number }>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* TODO: seems the same as findMany, it's not returning count by default
|
|
134
|
+
* @deprecated
|
|
135
|
+
*/
|
|
136
|
+
findWithRelationCounts<
|
|
137
|
+
TContentTypeUID extends Common.UID.Schema,
|
|
138
|
+
TParams extends Params.Pick<
|
|
139
|
+
TContentTypeUID,
|
|
140
|
+
| 'fields'
|
|
141
|
+
| 'filters'
|
|
142
|
+
| '_q'
|
|
143
|
+
| 'pagination:offset'
|
|
144
|
+
| 'sort'
|
|
145
|
+
| 'populate'
|
|
146
|
+
| 'publicationState'
|
|
147
|
+
| 'plugin'
|
|
148
|
+
>
|
|
149
|
+
>(
|
|
150
|
+
uid: TContentTypeUID,
|
|
151
|
+
params?: TParams
|
|
152
|
+
): Promise<Result<TContentTypeUID, TParams>[]>;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @deprecated
|
|
156
|
+
*/
|
|
157
|
+
findWithRelationCountsPage<
|
|
158
|
+
TContentTypeUID extends Common.UID.Schema,
|
|
159
|
+
TParams extends Params.Pick<
|
|
160
|
+
TContentTypeUID,
|
|
161
|
+
| 'fields'
|
|
162
|
+
| 'filters'
|
|
163
|
+
| '_q'
|
|
164
|
+
| 'pagination'
|
|
165
|
+
| 'sort'
|
|
166
|
+
| 'populate'
|
|
167
|
+
| 'publicationState'
|
|
168
|
+
| 'plugin'
|
|
169
|
+
>
|
|
170
|
+
>(
|
|
171
|
+
uid: TContentTypeUID,
|
|
172
|
+
params?: TParams
|
|
173
|
+
): Promise<PaginatedResult<TContentTypeUID, TParams>>;
|
|
174
|
+
|
|
175
|
+
count<TContentTypeUID extends Common.UID.ContentType>(
|
|
176
|
+
uid: TContentTypeUID,
|
|
177
|
+
params?: Params.Pick<TContentTypeUID, 'filters' | '_q'>
|
|
178
|
+
): Promise<number>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* TODO: Considering making this API public include providing a valid return type
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
184
|
+
load<
|
|
185
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
186
|
+
TField extends Attribute.GetPopulatableKeys<TContentTypeUID>
|
|
187
|
+
>(
|
|
188
|
+
uid: TContentTypeUID,
|
|
189
|
+
entity: PartialEntity<TContentTypeUID>,
|
|
190
|
+
field: Utils.Guard.Never<TField, string>,
|
|
191
|
+
params?: GetPopulatableFieldParams<TContentTypeUID, TField>
|
|
192
|
+
): Promise<any>;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* TODO: Considering making this API public include providing a valid return type
|
|
196
|
+
* @internal
|
|
197
|
+
*/
|
|
198
|
+
loadPages<
|
|
199
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
200
|
+
TField extends Attribute.GetPopulatableKeys<TContentTypeUID>
|
|
201
|
+
>(
|
|
202
|
+
uid: TContentTypeUID,
|
|
203
|
+
entity: PartialEntity<TContentTypeUID>,
|
|
204
|
+
field: Utils.Guard.Never<TField, string>,
|
|
205
|
+
params?: GetPopulatableFieldParams<TContentTypeUID, TField>,
|
|
206
|
+
pagination?: Params.Pagination.Any
|
|
207
|
+
): Promise<any>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
type GetPopulatableFieldParams<
|
|
211
|
+
TContentTypeUID extends Common.UID.ContentType,
|
|
212
|
+
TField extends Attribute.GetPopulatableKeys<TContentTypeUID>
|
|
213
|
+
> = Utils.Expression.MatchFirst<
|
|
214
|
+
[
|
|
215
|
+
[
|
|
216
|
+
Attribute.HasTarget<TContentTypeUID, TField>,
|
|
217
|
+
Params.Populate.NestedParams<Attribute.GetTarget<TContentTypeUID, TField>>
|
|
218
|
+
],
|
|
219
|
+
[
|
|
220
|
+
Attribute.HasMorphTargets<TContentTypeUID, TField>,
|
|
221
|
+
(
|
|
222
|
+
| Params.Populate.Fragment<Attribute.GetMorphTargets<TContentTypeUID, TField>>
|
|
223
|
+
| Params.Populate.NestedParams<Common.UID.Schema>
|
|
224
|
+
)
|
|
225
|
+
]
|
|
226
|
+
],
|
|
227
|
+
Params.Populate.Fragment<Common.UID.Schema> | Params.Populate.NestedParams<Common.UID.Schema>
|
|
228
|
+
>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { Attribute, Common, Utils } from '@strapi/strapi';
|
|
2
|
+
|
|
3
|
+
export type NonFilterableKind = Extract<Attribute.Kind, 'password' | 'dynamiczone'>;
|
|
4
|
+
export type FilterableKind = Exclude<Attribute.Kind, NonFilterableKind>;
|
|
5
|
+
|
|
6
|
+
export type GetNonFilterableKeys<TSchemaUID extends Common.UID.Schema> = Utils.Object.KeysBy<
|
|
7
|
+
Attribute.GetAll<TSchemaUID>,
|
|
8
|
+
Attribute.OfType<NonFilterableKind>
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
export type GetScalarKeys<TSchemaUID extends Common.UID.Schema> = Exclude<
|
|
12
|
+
Attribute.GetKeysByType<TSchemaUID, Attribute.NonPopulatableKind>,
|
|
13
|
+
GetNonFilterableKeys<TSchemaUID>
|
|
14
|
+
>;
|
|
15
|
+
|
|
16
|
+
export type GetNestedKeys<TSchemaUID extends Common.UID.Schema> = Exclude<
|
|
17
|
+
Attribute.GetKeysWithTarget<TSchemaUID>,
|
|
18
|
+
GetNonFilterableKeys<TSchemaUID>
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
export type ID = `${number}` | number;
|
|
22
|
+
|
|
23
|
+
export type BooleanValue = boolean | 'true' | 'false' | 't' | 'f' | '1' | '0' | 1 | 0;
|
|
24
|
+
|
|
25
|
+
export type NumberValue = string | number;
|
|
26
|
+
|
|
27
|
+
export type DateValue = Attribute.DateValue | number;
|
|
28
|
+
|
|
29
|
+
export type TimeValue = Attribute.TimeValue | number;
|
|
30
|
+
|
|
31
|
+
export type DateTimeValue = Attribute.DateTimeValue | number;
|
|
32
|
+
|
|
33
|
+
export type TimeStampValue = Attribute.TimestampValue;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List of possible values for the scalar attributes
|
|
37
|
+
* Uses the local GetValue to benefit from the values' overrides
|
|
38
|
+
*/
|
|
39
|
+
export type ScalarValues = GetValue<
|
|
40
|
+
| Attribute.BigInteger
|
|
41
|
+
| Attribute.Boolean
|
|
42
|
+
| Attribute.DateTime
|
|
43
|
+
| Attribute.Date
|
|
44
|
+
| Attribute.Decimal
|
|
45
|
+
| Attribute.Email
|
|
46
|
+
| Attribute.Enumeration<string[]>
|
|
47
|
+
| Attribute.Float
|
|
48
|
+
| Attribute.Integer
|
|
49
|
+
| Attribute.JSON
|
|
50
|
+
// /!\ Password attributes are NOT filterable and should NOT be part of this union type.
|
|
51
|
+
// The member below has been commented on purpose to avoid adding it back without noticing.
|
|
52
|
+
// | Attribute.Password
|
|
53
|
+
| Attribute.RichText
|
|
54
|
+
| Attribute.String
|
|
55
|
+
| Attribute.Text
|
|
56
|
+
| Attribute.Time
|
|
57
|
+
| Attribute.Timestamp
|
|
58
|
+
| Attribute.UID<Common.UID.Schema | undefined>
|
|
59
|
+
>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Attribute.GetValues override with extended values
|
|
63
|
+
*/
|
|
64
|
+
export type GetValues<TSchemaUID extends Common.UID.Schema> = OmitRelationWithoutTarget<
|
|
65
|
+
TSchemaUID,
|
|
66
|
+
{
|
|
67
|
+
[TKey in Attribute.GetOptionalKeys<TSchemaUID>]?: GetValue<Attribute.Get<TSchemaUID, TKey>>;
|
|
68
|
+
} & {
|
|
69
|
+
[TKey in Attribute.GetRequiredKeys<TSchemaUID>]-?: GetValue<Attribute.Get<TSchemaUID, TKey>>;
|
|
70
|
+
}
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
export type OmitRelationWithoutTarget<TSchemaUID extends Common.UID.Schema, TValue> = Omit<
|
|
74
|
+
TValue,
|
|
75
|
+
Exclude<Attribute.GetKeysByType<TSchemaUID, 'relation'>, Attribute.GetKeysWithTarget<TSchemaUID>>
|
|
76
|
+
>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Attribute.GetValue override with extended values
|
|
80
|
+
*
|
|
81
|
+
* Fallback to unknown if never is found
|
|
82
|
+
*/
|
|
83
|
+
export type GetValue<TAttribute extends Attribute.Attribute> = Utils.Expression.If<
|
|
84
|
+
Utils.Expression.IsNotNever<TAttribute>,
|
|
85
|
+
Utils.Expression.MatchFirst<
|
|
86
|
+
[
|
|
87
|
+
// Relation
|
|
88
|
+
[
|
|
89
|
+
Utils.Expression.Extends<TAttribute, Attribute.OfType<'relation'>>,
|
|
90
|
+
TAttribute extends Attribute.Relation<infer _TOrigin, infer TRelationKind, infer TTarget>
|
|
91
|
+
? Utils.Expression.If<
|
|
92
|
+
Utils.Expression.IsNotNever<TTarget>,
|
|
93
|
+
Attribute.RelationPluralityModifier<TRelationKind, ID>
|
|
94
|
+
>
|
|
95
|
+
: never
|
|
96
|
+
],
|
|
97
|
+
// DynamicZone
|
|
98
|
+
[
|
|
99
|
+
Utils.Expression.Extends<TAttribute, Attribute.OfType<'dynamiczone'>>,
|
|
100
|
+
TAttribute extends Attribute.DynamicZone<infer TComponentsUIDs>
|
|
101
|
+
? Array<
|
|
102
|
+
// Extract tuple values to a component uid union type
|
|
103
|
+
Utils.Array.Values<TComponentsUIDs> extends infer TComponentUID
|
|
104
|
+
? TComponentUID extends Common.UID.Component
|
|
105
|
+
? GetValues<TComponentUID> & { __component: TComponentUID }
|
|
106
|
+
: never
|
|
107
|
+
: never
|
|
108
|
+
>
|
|
109
|
+
: never
|
|
110
|
+
],
|
|
111
|
+
// Component
|
|
112
|
+
[
|
|
113
|
+
Utils.Expression.Extends<TAttribute, Attribute.OfType<'component'>>,
|
|
114
|
+
TAttribute extends Attribute.Component<infer TComponentUID, infer TRepeatable>
|
|
115
|
+
? TComponentUID extends Common.UID.Component
|
|
116
|
+
? GetValues<TComponentUID> extends infer TValues
|
|
117
|
+
? Utils.Expression.If<TRepeatable, TValues[], TValues>
|
|
118
|
+
: never
|
|
119
|
+
: never
|
|
120
|
+
: never
|
|
121
|
+
],
|
|
122
|
+
// Boolean
|
|
123
|
+
[Utils.Expression.Extends<TAttribute, Attribute.Boolean>, BooleanValue],
|
|
124
|
+
// Number
|
|
125
|
+
[
|
|
126
|
+
Utils.Expression.Extends<
|
|
127
|
+
TAttribute,
|
|
128
|
+
Attribute.Integer | Attribute.BigInteger | Attribute.Float | Attribute.Decimal
|
|
129
|
+
>,
|
|
130
|
+
NumberValue
|
|
131
|
+
],
|
|
132
|
+
// Date / Time
|
|
133
|
+
[Utils.Expression.Extends<TAttribute, Attribute.Time>, TimeValue],
|
|
134
|
+
[Utils.Expression.Extends<TAttribute, Attribute.Date>, DateValue],
|
|
135
|
+
[
|
|
136
|
+
Utils.Expression.Extends<TAttribute, Attribute.Timestamp | Attribute.DateTime>,
|
|
137
|
+
DateTimeValue
|
|
138
|
+
],
|
|
139
|
+
// Fallback
|
|
140
|
+
// If none of the above attribute type, fallback to the original Attribute.GetValue (while making sure it's an attribute)
|
|
141
|
+
[Utils.Expression.True, Attribute.GetValue<TAttribute, unknown>]
|
|
142
|
+
],
|
|
143
|
+
unknown
|
|
144
|
+
>,
|
|
145
|
+
unknown
|
|
146
|
+
>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Attribute, Common, Utils } from '@strapi/strapi';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wildcard notation for the fields.
|
|
5
|
+
*
|
|
6
|
+
* When used, it represents every non-populatable field from the given schema
|
|
7
|
+
*/
|
|
8
|
+
export type WildcardNotation = '*';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Single non-populatable attribute representation
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* type A = 'title'; // ✅
|
|
15
|
+
* type B = 'description'; // ✅
|
|
16
|
+
* type C = 'populatableField'; // ❌
|
|
17
|
+
* type D = '<random_string>'; // ❌
|
|
18
|
+
*/
|
|
19
|
+
export type SingleAttribute<TSchemaUID extends Common.UID.Schema> =
|
|
20
|
+
| 'id'
|
|
21
|
+
| Utils.Guard.Never<Attribute.GetNonPopulatableKeys<TSchemaUID>, string>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Union of all possible string representation for fields
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* type A = 'title'; // ✅
|
|
28
|
+
* type B = 'title,description'; // ✅
|
|
29
|
+
* type C = 'id'; // ✅
|
|
30
|
+
* type D = '*'; // ✅
|
|
31
|
+
* type E = 'populatableField'; // ❌
|
|
32
|
+
* type F = '<random_string>'; // ❌
|
|
33
|
+
*/
|
|
34
|
+
export type StringNotation<TSchemaUID extends Common.UID.Schema> =
|
|
35
|
+
| WildcardNotation
|
|
36
|
+
| SingleAttribute<TSchemaUID>
|
|
37
|
+
// TODO: Loose type checking to avoid circular dependencies & infinite recursion
|
|
38
|
+
| `${string},${string}`;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Array notation for fields
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* type A = ['title']; // ✅
|
|
45
|
+
* type B = ['title', 'description']; // ✅
|
|
46
|
+
* type C = ['id']; // ✅
|
|
47
|
+
* type E = ['*']; // ❌
|
|
48
|
+
* type F = ['populatableField']; // ❌
|
|
49
|
+
* type G = ['<random_string>']; // ❌
|
|
50
|
+
*/
|
|
51
|
+
export type ArrayNotation<TSchemaUID extends Common.UID.Schema> = Exclude<
|
|
52
|
+
StringNotation<TSchemaUID>,
|
|
53
|
+
WildcardNotation
|
|
54
|
+
>[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Represents any notation for a sort (string, array, object)
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* type A = '*'; // ✅
|
|
61
|
+
* type B = 'id'; // ✅
|
|
62
|
+
* type C = 'title'; // ✅
|
|
63
|
+
* type D = 'title,description'; // ✅
|
|
64
|
+
* type E = ['title', 'description']; // ✅
|
|
65
|
+
* type F = [id, 'title,description']; // ✅
|
|
66
|
+
* type G = ['*']; // ❌
|
|
67
|
+
* type H = ['populatableField']; // ❌
|
|
68
|
+
* type I = ['<random_string>']; // ❌
|
|
69
|
+
* type J = 'populatableField'; // ❌
|
|
70
|
+
* type K = '<random_string>'; // ❌
|
|
71
|
+
*/
|
|
72
|
+
export type Any<TSchemaUID extends Common.UID.Schema> =
|
|
73
|
+
| StringNotation<TSchemaUID>
|
|
74
|
+
| ArrayNotation<TSchemaUID>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Attribute, Common, Utils } from '@strapi/strapi';
|
|
2
|
+
|
|
3
|
+
import type * as Operator from './operators';
|
|
4
|
+
import type * as AttributeUtils from '../attributes';
|
|
5
|
+
|
|
6
|
+
export { Operator };
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Filter representation for nested attributes
|
|
10
|
+
*/
|
|
11
|
+
type NestedAttributeCondition<
|
|
12
|
+
TSchemaUID extends Common.UID.Schema,
|
|
13
|
+
TAttributeName extends Attribute.GetKeys<TSchemaUID>
|
|
14
|
+
> = ObjectNotation<
|
|
15
|
+
Utils.Guard.Never<Attribute.GetTarget<TSchemaUID, TAttributeName>, Common.UID.Schema>
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Filter representation for scalar attributes
|
|
20
|
+
*/
|
|
21
|
+
type AttributeCondition<
|
|
22
|
+
TSchemaUID extends Common.UID.Schema,
|
|
23
|
+
TAttributeName extends Attribute.GetKeys<TSchemaUID>
|
|
24
|
+
> = Utils.Expression.If<
|
|
25
|
+
Utils.Expression.IsNotNever<TAttributeName>,
|
|
26
|
+
// Get the filter attribute value for the given attribute
|
|
27
|
+
AttributeUtils.GetValue<Attribute.Get<TSchemaUID, TAttributeName>>,
|
|
28
|
+
// Fallback to the list of all possible scalar attributes' value if the attribute is not valid (never)
|
|
29
|
+
AttributeUtils.ScalarValues
|
|
30
|
+
> extends infer TAttributeValue
|
|
31
|
+
?
|
|
32
|
+
| TAttributeValue // Implicit $eq operator
|
|
33
|
+
| ({
|
|
34
|
+
[TIter in Operator.BooleanValue]?: boolean;
|
|
35
|
+
} & {
|
|
36
|
+
[TIter in Operator.DynamicValue]?: TAttributeValue;
|
|
37
|
+
} & {
|
|
38
|
+
[TIter in Operator.DynamicArrayValue]?: TAttributeValue[];
|
|
39
|
+
} & {
|
|
40
|
+
[TIter in Operator.DynamicBoundValue]?: [TAttributeValue, TAttributeValue];
|
|
41
|
+
} & {
|
|
42
|
+
[TIter in Operator.Logical]?: AttributeCondition<TSchemaUID, TAttributeName>;
|
|
43
|
+
} & {
|
|
44
|
+
[TIter in Operator.Group]?: AttributeCondition<TSchemaUID, TAttributeName>[];
|
|
45
|
+
})
|
|
46
|
+
: never;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Tree representation of a Strapi filter for a given schema UID
|
|
50
|
+
*/
|
|
51
|
+
export type ObjectNotation<TSchemaUID extends Common.UID.Schema> = {
|
|
52
|
+
[TIter in Operator.Group]?: ObjectNotation<TSchemaUID>[];
|
|
53
|
+
} & {
|
|
54
|
+
[TIter in Operator.Logical]?: ObjectNotation<TSchemaUID>;
|
|
55
|
+
} & ([AttributeUtils.GetScalarKeys<TSchemaUID>, AttributeUtils.GetNestedKeys<TSchemaUID>] extends [
|
|
56
|
+
infer TScalarKeys extends AttributeUtils.GetScalarKeys<TSchemaUID>,
|
|
57
|
+
infer TNestedKeys extends AttributeUtils.GetNestedKeys<TSchemaUID>
|
|
58
|
+
]
|
|
59
|
+
? // If both the scalar and nested keys are resolved, then create a strongly
|
|
60
|
+
// typed filter object, else create a loose generic abstraction.
|
|
61
|
+
Utils.Expression.If<
|
|
62
|
+
Utils.Expression.And<
|
|
63
|
+
Utils.Expression.IsNotNever<TScalarKeys>,
|
|
64
|
+
Utils.Expression.IsNotNever<TNestedKeys>
|
|
65
|
+
>,
|
|
66
|
+
// Strongly typed representation of the filter object tree
|
|
67
|
+
| { [TIter in TScalarKeys]?: AttributeCondition<TSchemaUID, TIter> }
|
|
68
|
+
| { [TIter in TNestedKeys]?: NestedAttributeCondition<TSchemaUID, TIter> },
|
|
69
|
+
// Generic representation of the filter object tree in case we don't have access to the attributes' list
|
|
70
|
+
| { [TKey in string]?: AttributeCondition<TSchemaUID, never> }
|
|
71
|
+
| { [TKey in string]?: NestedAttributeCondition<TSchemaUID, never> }
|
|
72
|
+
>
|
|
73
|
+
: never);
|
|
74
|
+
|
|
75
|
+
export type Any<TSchemaUID extends Common.UID.Schema> = ObjectNotation<TSchemaUID>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type Array = '$in' | '$notIn' | '$between';
|
|
2
|
+
|
|
3
|
+
export type Group = '$and' | '$or';
|
|
4
|
+
|
|
5
|
+
export type Logical = '$not';
|
|
6
|
+
|
|
7
|
+
export type BooleanValue = '$null' | '$notNull';
|
|
8
|
+
|
|
9
|
+
export type DynamicValue =
|
|
10
|
+
| '$eq'
|
|
11
|
+
| '$eqi'
|
|
12
|
+
| '$ne'
|
|
13
|
+
| '$gt'
|
|
14
|
+
| '$gte'
|
|
15
|
+
| '$lt'
|
|
16
|
+
| '$lte'
|
|
17
|
+
| '$startsWith'
|
|
18
|
+
| '$endsWith'
|
|
19
|
+
| '$startsWithi'
|
|
20
|
+
| '$endsWithi'
|
|
21
|
+
| '$contains'
|
|
22
|
+
| '$notContains'
|
|
23
|
+
| '$containsi'
|
|
24
|
+
| '$notContainsi';
|
|
25
|
+
|
|
26
|
+
export type DynamicArrayValue = '$in' | '$notIn';
|
|
27
|
+
|
|
28
|
+
export type DynamicBoundValue = '$between';
|
|
29
|
+
|
|
30
|
+
export type Where = BooleanValue | DynamicValue | DynamicArrayValue | DynamicBoundValue;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Common, EntityService, Utils } from '@strapi/strapi';
|
|
2
|
+
// Params
|
|
3
|
+
import type * as Sort from './sort';
|
|
4
|
+
import type * as Pagination from './pagination';
|
|
5
|
+
import type * as Fields from './fields';
|
|
6
|
+
import type * as Filters from './filters';
|
|
7
|
+
import type * as Populate from './populate';
|
|
8
|
+
import type * as PublicationState from './publication-state';
|
|
9
|
+
import type * as Data from './data';
|
|
10
|
+
import type * as Search from './search';
|
|
11
|
+
|
|
12
|
+
// Utils
|
|
13
|
+
import type * as Attribute from './attributes';
|
|
14
|
+
|
|
15
|
+
export type Pick<
|
|
16
|
+
TSchemaUID extends Common.UID.Schema,
|
|
17
|
+
TKind extends Kind
|
|
18
|
+
> = Utils.Expression.MatchAllIntersect<
|
|
19
|
+
[
|
|
20
|
+
// Sort
|
|
21
|
+
[HasMember<TKind, 'sort'>, { sort?: Sort.Any<TSchemaUID> }],
|
|
22
|
+
[HasMember<TKind, 'sort:string'>, { sort?: Sort.StringNotation<TSchemaUID> }],
|
|
23
|
+
[HasMember<TKind, 'sort:array'>, { sort?: Sort.ArrayNotation<TSchemaUID> }],
|
|
24
|
+
[HasMember<TKind, 'sort:object'>, { sort?: Sort.ObjectNotation<TSchemaUID> }],
|
|
25
|
+
// Fields
|
|
26
|
+
[HasMember<TKind, 'fields'>, { fields?: Fields.Any<TSchemaUID> }],
|
|
27
|
+
[HasMember<TKind, 'fields:string'>, { fields?: Fields.StringNotation<TSchemaUID> }],
|
|
28
|
+
[HasMember<TKind, 'fields:array'>, { fields?: Fields.ArrayNotation<TSchemaUID> }],
|
|
29
|
+
// Filters
|
|
30
|
+
[HasMember<TKind, 'filters'>, { filters?: Filters.Any<TSchemaUID> }],
|
|
31
|
+
// Populate
|
|
32
|
+
[HasMember<TKind, 'populate'>, { populate?: Populate.Any<TSchemaUID> }],
|
|
33
|
+
[HasMember<TKind, 'populate:string'>, { populate?: Populate.StringNotation<TSchemaUID> }],
|
|
34
|
+
[HasMember<TKind, 'populate:array'>, { populate?: Populate.ArrayNotation<TSchemaUID> }],
|
|
35
|
+
[HasMember<TKind, 'populate:object'>, { populate?: Populate.ObjectNotation<TSchemaUID> }],
|
|
36
|
+
// Pagination
|
|
37
|
+
[HasMember<TKind, 'pagination'>, Pagination.Any],
|
|
38
|
+
[HasMember<TKind, 'pagination:offset'>, Pagination.OffsetNotation],
|
|
39
|
+
[HasMember<TKind, 'pagination:page'>, Pagination.PageNotation],
|
|
40
|
+
// Publication State
|
|
41
|
+
[HasMember<TKind, 'publicationState'>, PublicationState.For<TSchemaUID>],
|
|
42
|
+
// Plugin
|
|
43
|
+
[HasMember<TKind, 'plugin'>, EntityService.GetPluginParams<TSchemaUID>],
|
|
44
|
+
// Data
|
|
45
|
+
[HasMember<TKind, 'data'>, { data?: Data.Input<TSchemaUID> }],
|
|
46
|
+
[HasMember<TKind, 'data:partial'>, { data?: Partial<Data.Input<TSchemaUID>> }],
|
|
47
|
+
// Files
|
|
48
|
+
[HasMember<TKind, 'files'>, { files?: unknown }], // TODO
|
|
49
|
+
// Search
|
|
50
|
+
[HasMember<TKind, '_q'>, { _q?: Search.Q }]
|
|
51
|
+
]
|
|
52
|
+
>;
|
|
53
|
+
|
|
54
|
+
export type Kind =
|
|
55
|
+
| 'sort'
|
|
56
|
+
| 'sort:string'
|
|
57
|
+
| 'sort:array'
|
|
58
|
+
| 'sort:object'
|
|
59
|
+
| 'fields'
|
|
60
|
+
| 'fields:string'
|
|
61
|
+
| 'fields:array'
|
|
62
|
+
| 'filters'
|
|
63
|
+
| 'populate'
|
|
64
|
+
| 'populate:string'
|
|
65
|
+
| 'populate:array'
|
|
66
|
+
| 'populate:object'
|
|
67
|
+
| 'pagination'
|
|
68
|
+
| 'pagination:offset'
|
|
69
|
+
| 'pagination:page'
|
|
70
|
+
| 'publicationState'
|
|
71
|
+
| 'plugin'
|
|
72
|
+
| 'data'
|
|
73
|
+
| 'data:partial'
|
|
74
|
+
| 'files'
|
|
75
|
+
| '_q';
|
|
76
|
+
|
|
77
|
+
type HasMember<TValue extends Kind, TTest extends Kind> = Utils.Expression.Extends<TTest, TValue>;
|
|
78
|
+
|
|
79
|
+
export type { Sort, Pagination, Fields, Filters, Populate, PublicationState, Data, Attribute };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Utils } from '@strapi/strapi';
|
|
2
|
+
|
|
3
|
+
export type PageNotation = {
|
|
4
|
+
page?: number;
|
|
5
|
+
pageSize?: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type OffsetNotation = {
|
|
9
|
+
start?: number;
|
|
10
|
+
limit?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Any = Utils.XOR<PageNotation, OffsetNotation>;
|