@contember/bindx 0.1.5 → 0.1.9
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/adapter/ContemberAdapter.d.ts +11 -14
- package/dist/adapter/ContemberAdapter.d.ts.map +1 -1
- package/dist/brand/ComponentBrand.d.ts +1 -24
- package/dist/brand/ComponentBrand.d.ts.map +1 -1
- package/dist/contember/index.d.ts +1 -2
- package/dist/contember/index.d.ts.map +1 -1
- package/dist/handles/EntityHandle.d.ts +18 -29
- package/dist/handles/EntityHandle.d.ts.map +1 -1
- package/dist/handles/FieldHandle.d.ts +5 -3
- package/dist/handles/FieldHandle.d.ts.map +1 -1
- package/dist/handles/HasManyListHandle.d.ts +4 -3
- package/dist/handles/HasManyListHandle.d.ts.map +1 -1
- package/dist/handles/HasOneHandle.d.ts +33 -36
- package/dist/handles/HasOneHandle.d.ts.map +1 -1
- package/dist/handles/PlaceholderHandle.d.ts +9 -19
- package/dist/handles/PlaceholderHandle.d.ts.map +1 -1
- package/dist/handles/proxyFactory.d.ts +9 -37
- package/dist/handles/proxyFactory.d.ts.map +1 -1
- package/dist/handles/types.d.ts +4 -0
- package/dist/handles/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/persistence/ContemberSchemaMutationAdapter.d.ts +24 -1
- package/dist/persistence/ContemberSchemaMutationAdapter.d.ts.map +1 -1
- package/dist/schema/ContemberSchema.d.ts +1 -97
- package/dist/schema/ContemberSchema.d.ts.map +1 -1
- package/dist/schema/SchemaLoader.d.ts +1 -27
- package/dist/schema/SchemaLoader.d.ts.map +1 -1
- package/dist/schema/SchemaRegistry.d.ts +1 -94
- package/dist/schema/SchemaRegistry.d.ts.map +1 -1
- package/dist/schema/roles.d.ts +1 -61
- package/dist/schema/roles.d.ts.map +1 -1
- package/dist/schema/types.d.ts +1 -178
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/selection/SelectionMetaCollector.d.ts +1 -31
- package/dist/selection/SelectionMetaCollector.d.ts.map +1 -1
- package/dist/selection/SelectionScope.d.ts +1 -76
- package/dist/selection/SelectionScope.d.ts.map +1 -1
- package/dist/selection/buildQuery.d.ts +1 -44
- package/dist/selection/buildQuery.d.ts.map +1 -1
- package/dist/selection/createFragment.d.ts +1 -28
- package/dist/selection/createFragment.d.ts.map +1 -1
- package/dist/selection/createSelectionBuilder.d.ts +1 -17
- package/dist/selection/createSelectionBuilder.d.ts.map +1 -1
- package/dist/selection/queryTypes.d.ts +1 -83
- package/dist/selection/queryTypes.d.ts.map +1 -1
- package/dist/selection/types.d.ts +1 -237
- package/dist/selection/types.d.ts.map +1 -1
- package/dist/utils/aliasGenerator.d.ts +1 -24
- package/dist/utils/aliasGenerator.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapter/ContemberAdapter.ts +193 -123
- package/src/brand/ComponentBrand.ts +1 -28
- package/src/contember/index.ts +1 -8
- package/src/handles/EntityHandle.ts +131 -61
- package/src/handles/FieldHandle.ts +19 -3
- package/src/handles/HasManyListHandle.ts +15 -12
- package/src/handles/HasOneHandle.ts +98 -66
- package/src/handles/PlaceholderHandle.ts +26 -24
- package/src/handles/proxyFactory.ts +29 -128
- package/src/handles/types.ts +6 -0
- package/src/index.ts +22 -3
- package/src/persistence/ContemberSchemaMutationAdapter.ts +19 -1
- package/src/schema/ContemberSchema.ts +14 -132
- package/src/schema/SchemaLoader.ts +1 -93
- package/src/schema/SchemaRegistry.ts +1 -286
- package/src/schema/roles.ts +10 -83
- package/src/schema/types.ts +21 -238
- package/src/selection/SelectionMetaCollector.ts +1 -122
- package/src/selection/SelectionScope.ts +1 -208
- package/src/selection/buildQuery.ts +1 -134
- package/src/selection/createFragment.ts +1 -50
- package/src/selection/createSelectionBuilder.ts +1 -283
- package/src/selection/queryTypes.ts +8 -135
- package/src/selection/types.ts +13 -320
- package/src/utils/aliasGenerator.ts +1 -56
package/src/selection/types.ts
CHANGED
|
@@ -1,320 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
export interface HasManyOptions<
|
|
16
|
-
TItem = unknown,
|
|
17
|
-
TAlias extends string = string,
|
|
18
|
-
> {
|
|
19
|
-
as?: TAlias
|
|
20
|
-
filter?: EntityWhere<TItem>
|
|
21
|
-
orderBy?: readonly EntityOrderBy<TItem>[]
|
|
22
|
-
limit?: number
|
|
23
|
-
offset?: number
|
|
24
|
-
totalCount?: boolean
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Metadata for a selected field (runtime)
|
|
29
|
-
*/
|
|
30
|
-
export interface SelectionFieldMeta {
|
|
31
|
-
/** Original field name in the entity */
|
|
32
|
-
fieldName: string
|
|
33
|
-
/** Alias (output key) - defaults to fieldName */
|
|
34
|
-
alias: string
|
|
35
|
-
/** Full path to this field (for JSX components) */
|
|
36
|
-
path: string[]
|
|
37
|
-
/** Whether this is a relation (has nested fields) */
|
|
38
|
-
isRelation: boolean
|
|
39
|
-
/** Whether this is an array/has-many relation */
|
|
40
|
-
isArray: boolean
|
|
41
|
-
/** For relations: nested selection metadata */
|
|
42
|
-
nested?: SelectionMeta
|
|
43
|
-
/** For has-many: additional parameters */
|
|
44
|
-
hasManyParams?: {
|
|
45
|
-
filter?: unknown
|
|
46
|
-
orderBy?: unknown
|
|
47
|
-
limit?: number
|
|
48
|
-
offset?: number
|
|
49
|
-
totalCount?: boolean
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Runtime metadata for a complete selection
|
|
55
|
-
*/
|
|
56
|
-
export interface SelectionMeta {
|
|
57
|
-
fields: Map<string, SelectionFieldMeta>
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Extract item type from array
|
|
62
|
-
*/
|
|
63
|
-
type ArrayItemType<T> = T extends Array<infer U> ? U : never
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* A fragment defined with the fluent builder
|
|
67
|
-
*
|
|
68
|
-
* @typeParam TModel - The entity model type
|
|
69
|
-
* @typeParam TResult - The selected fields result type
|
|
70
|
-
* @typeParam TBrand - Component brand type for validation (defaults to AnyBrand)
|
|
71
|
-
*/
|
|
72
|
-
export interface FluentFragment<
|
|
73
|
-
TModel,
|
|
74
|
-
TResult,
|
|
75
|
-
TBrand extends AnyBrand = AnyBrand,
|
|
76
|
-
> {
|
|
77
|
-
/** Runtime metadata */
|
|
78
|
-
readonly __meta: SelectionMeta
|
|
79
|
-
/** Type brand for result type */
|
|
80
|
-
readonly __resultType: TResult
|
|
81
|
-
/** Type brand for model type */
|
|
82
|
-
readonly __modelType: TModel
|
|
83
|
-
/** Marker for type checking */
|
|
84
|
-
readonly __isFragment: true
|
|
85
|
-
/** Component brand for type-level tracking */
|
|
86
|
-
readonly __brand?: TBrand
|
|
87
|
-
/** Runtime brand symbols for validation */
|
|
88
|
-
readonly __brands?: Set<symbol>
|
|
89
|
-
/** Runtime roles for validation */
|
|
90
|
-
readonly __roles?: readonly string[]
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Scalar method on selection builder - selects a scalar field
|
|
95
|
-
*/
|
|
96
|
-
export interface ScalarMethod<TEntity, K extends keyof TEntity, TSelected extends object, THasManyParams extends object> {
|
|
97
|
-
/** Select field with original name */
|
|
98
|
-
(): SelectionBuilder<TEntity, TSelected & Pick<TEntity, K>, THasManyParams>
|
|
99
|
-
/** Select field with alias */
|
|
100
|
-
<TAlias extends string>(options: { as: TAlias }): SelectionBuilder<
|
|
101
|
-
TEntity,
|
|
102
|
-
TSelected & { [P in TAlias]: TEntity[K] },
|
|
103
|
-
THasManyParams
|
|
104
|
-
>
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Has-one method on selection builder - selects a relation to single entity
|
|
109
|
-
*/
|
|
110
|
-
export interface HasOneMethod<
|
|
111
|
-
TEntity,
|
|
112
|
-
K extends keyof TEntity,
|
|
113
|
-
TRelated,
|
|
114
|
-
TSelected extends object,
|
|
115
|
-
THasManyParams extends object,
|
|
116
|
-
> {
|
|
117
|
-
/** Select with inline callback */
|
|
118
|
-
<TNestedSelected extends object>(
|
|
119
|
-
selector: (builder: SelectionBuilder<TRelated>) => SelectionBuilder<TRelated, TNestedSelected, object>,
|
|
120
|
-
): SelectionBuilder<TEntity, TSelected & { [P in K & string]: TNestedSelected }, THasManyParams>
|
|
121
|
-
|
|
122
|
-
/** Select with fragment */
|
|
123
|
-
<TFragmentResult extends object>(
|
|
124
|
-
fragment: FluentFragment<TRelated, TFragmentResult>,
|
|
125
|
-
): SelectionBuilder<TEntity, TSelected & { [P in K & string]: TFragmentResult }, THasManyParams>
|
|
126
|
-
|
|
127
|
-
/** Select with multiple fragments (merged) - result type is intersection of all fragment result types */
|
|
128
|
-
<T1 extends object, T2 extends object>(
|
|
129
|
-
fragment1: FluentFragment<TRelated, T1>,
|
|
130
|
-
fragment2: FluentFragment<TRelated, T2>,
|
|
131
|
-
): SelectionBuilder<TEntity, TSelected & { [P in K & string]: T1 & T2 }, THasManyParams>
|
|
132
|
-
|
|
133
|
-
/** Select with three fragments (merged) */
|
|
134
|
-
<T1 extends object, T2 extends object, T3 extends object>(
|
|
135
|
-
fragment1: FluentFragment<TRelated, T1>,
|
|
136
|
-
fragment2: FluentFragment<TRelated, T2>,
|
|
137
|
-
fragment3: FluentFragment<TRelated, T3>,
|
|
138
|
-
): SelectionBuilder<TEntity, TSelected & { [P in K & string]: T1 & T2 & T3 }, THasManyParams>
|
|
139
|
-
|
|
140
|
-
/** Select with alias and callback */
|
|
141
|
-
<TAlias extends string, TNestedSelected extends object>(
|
|
142
|
-
options: { as: TAlias },
|
|
143
|
-
selector: (builder: SelectionBuilder<TRelated>) => SelectionBuilder<TRelated, TNestedSelected, object>,
|
|
144
|
-
): SelectionBuilder<TEntity, TSelected & { [P in TAlias]: TNestedSelected }, THasManyParams>
|
|
145
|
-
|
|
146
|
-
/** Select with alias and fragment */
|
|
147
|
-
<TAlias extends string, TFragmentResult extends object>(
|
|
148
|
-
options: { as: TAlias },
|
|
149
|
-
fragment: FluentFragment<TRelated, TFragmentResult>,
|
|
150
|
-
): SelectionBuilder<TEntity, TSelected & { [P in TAlias]: TFragmentResult }, THasManyParams>
|
|
151
|
-
|
|
152
|
-
/** Select with alias and two fragments (merged) */
|
|
153
|
-
<TAlias extends string, T1 extends object, T2 extends object>(
|
|
154
|
-
options: { as: TAlias },
|
|
155
|
-
fragment1: FluentFragment<TRelated, T1>,
|
|
156
|
-
fragment2: FluentFragment<TRelated, T2>,
|
|
157
|
-
): SelectionBuilder<TEntity, TSelected & { [P in TAlias]: T1 & T2 }, THasManyParams>
|
|
158
|
-
|
|
159
|
-
/** Select with alias and three fragments (merged) */
|
|
160
|
-
<TAlias extends string, T1 extends object, T2 extends object, T3 extends object>(
|
|
161
|
-
options: { as: TAlias },
|
|
162
|
-
fragment1: FluentFragment<TRelated, T1>,
|
|
163
|
-
fragment2: FluentFragment<TRelated, T2>,
|
|
164
|
-
fragment3: FluentFragment<TRelated, T3>,
|
|
165
|
-
): SelectionBuilder<TEntity, TSelected & { [P in TAlias]: T1 & T2 & T3 }, THasManyParams>
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Resolve alias from options or fall back to field name
|
|
170
|
-
*/
|
|
171
|
-
type ResolveAlias<K, TOptions> = TOptions extends { as: infer A extends string } ? A : K & string
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Has-many method on selection builder - selects a relation to multiple entities
|
|
175
|
-
*/
|
|
176
|
-
export interface HasManyMethod<
|
|
177
|
-
TEntity,
|
|
178
|
-
K extends keyof TEntity,
|
|
179
|
-
TItem,
|
|
180
|
-
TSelected extends object,
|
|
181
|
-
THasManyParams extends object,
|
|
182
|
-
> {
|
|
183
|
-
/** Select with inline callback (no options) */
|
|
184
|
-
<TNestedSelected extends object>(
|
|
185
|
-
selector: (builder: SelectionBuilder<TItem>) => SelectionBuilder<TItem, TNestedSelected, object>,
|
|
186
|
-
): SelectionBuilder<
|
|
187
|
-
TEntity,
|
|
188
|
-
TSelected & { [P in K & string]: TNestedSelected[] },
|
|
189
|
-
THasManyParams & { [P in K & string]: object }
|
|
190
|
-
>
|
|
191
|
-
|
|
192
|
-
/** Select with fragment (no options) */
|
|
193
|
-
<TFragmentResult extends object>(
|
|
194
|
-
fragment: FluentFragment<TItem, TFragmentResult>,
|
|
195
|
-
): SelectionBuilder<
|
|
196
|
-
TEntity,
|
|
197
|
-
TSelected & { [P in K & string]: TFragmentResult[] },
|
|
198
|
-
THasManyParams & { [P in K & string]: object }
|
|
199
|
-
>
|
|
200
|
-
|
|
201
|
-
/** Select with two fragments (merged, no options) */
|
|
202
|
-
<T1 extends object, T2 extends object>(
|
|
203
|
-
fragment1: FluentFragment<TItem, T1>,
|
|
204
|
-
fragment2: FluentFragment<TItem, T2>,
|
|
205
|
-
): SelectionBuilder<
|
|
206
|
-
TEntity,
|
|
207
|
-
TSelected & { [P in K & string]: (T1 & T2)[] },
|
|
208
|
-
THasManyParams & { [P in K & string]: object }
|
|
209
|
-
>
|
|
210
|
-
|
|
211
|
-
/** Select with three fragments (merged, no options) */
|
|
212
|
-
<T1 extends object, T2 extends object, T3 extends object>(
|
|
213
|
-
fragment1: FluentFragment<TItem, T1>,
|
|
214
|
-
fragment2: FluentFragment<TItem, T2>,
|
|
215
|
-
fragment3: FluentFragment<TItem, T3>,
|
|
216
|
-
): SelectionBuilder<
|
|
217
|
-
TEntity,
|
|
218
|
-
TSelected & { [P in K & string]: (T1 & T2 & T3)[] },
|
|
219
|
-
THasManyParams & { [P in K & string]: object }
|
|
220
|
-
>
|
|
221
|
-
|
|
222
|
-
/** Select with options and callback */
|
|
223
|
-
<TOptions extends HasManyOptions<TItem>, TNestedSelected extends object>(
|
|
224
|
-
options: TOptions,
|
|
225
|
-
selector: (builder: SelectionBuilder<TItem>) => SelectionBuilder<TItem, TNestedSelected, object>,
|
|
226
|
-
): SelectionBuilder<
|
|
227
|
-
TEntity,
|
|
228
|
-
TSelected & { [P in ResolveAlias<K, TOptions>]: TNestedSelected[] },
|
|
229
|
-
THasManyParams & { [P in ResolveAlias<K, TOptions>]: TOptions }
|
|
230
|
-
>
|
|
231
|
-
|
|
232
|
-
/** Select with options and fragment */
|
|
233
|
-
<TOptions extends HasManyOptions<TItem>, TFragmentResult extends object>(
|
|
234
|
-
options: TOptions,
|
|
235
|
-
fragment: FluentFragment<TItem, TFragmentResult>,
|
|
236
|
-
): SelectionBuilder<
|
|
237
|
-
TEntity,
|
|
238
|
-
TSelected & { [P in ResolveAlias<K, TOptions>]: TFragmentResult[] },
|
|
239
|
-
THasManyParams & { [P in ResolveAlias<K, TOptions>]: TOptions }
|
|
240
|
-
>
|
|
241
|
-
|
|
242
|
-
/** Select with options and two fragments (merged) */
|
|
243
|
-
<TOptions extends HasManyOptions<TItem>, T1 extends object, T2 extends object>(
|
|
244
|
-
options: TOptions,
|
|
245
|
-
fragment1: FluentFragment<TItem, T1>,
|
|
246
|
-
fragment2: FluentFragment<TItem, T2>,
|
|
247
|
-
): SelectionBuilder<
|
|
248
|
-
TEntity,
|
|
249
|
-
TSelected & { [P in ResolveAlias<K, TOptions>]: (T1 & T2)[] },
|
|
250
|
-
THasManyParams & { [P in ResolveAlias<K, TOptions>]: TOptions }
|
|
251
|
-
>
|
|
252
|
-
|
|
253
|
-
/** Select with options and three fragments (merged) */
|
|
254
|
-
<TOptions extends HasManyOptions<TItem>, T1 extends object, T2 extends object, T3 extends object>(
|
|
255
|
-
options: TOptions,
|
|
256
|
-
fragment1: FluentFragment<TItem, T1>,
|
|
257
|
-
fragment2: FluentFragment<TItem, T2>,
|
|
258
|
-
fragment3: FluentFragment<TItem, T3>,
|
|
259
|
-
): SelectionBuilder<
|
|
260
|
-
TEntity,
|
|
261
|
-
TSelected & { [P in ResolveAlias<K, TOptions>]: (T1 & T2 & T3)[] },
|
|
262
|
-
THasManyParams & { [P in ResolveAlias<K, TOptions>]: TOptions }
|
|
263
|
-
>
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Maps entity fields to their corresponding builder methods
|
|
268
|
-
*/
|
|
269
|
-
type SelectionBuilderMethods<TEntity, TSelected extends object, THasManyParams extends object> = {
|
|
270
|
-
[K in keyof TEntity]-?: TEntity[K] extends Array<infer U>
|
|
271
|
-
? HasManyMethod<TEntity, K, U, TSelected, THasManyParams>
|
|
272
|
-
: NonNullable<TEntity[K]> extends object
|
|
273
|
-
? HasOneMethod<TEntity, K, NonNullable<TEntity[K]>, TSelected, THasManyParams>
|
|
274
|
-
: ScalarMethod<TEntity, K, TSelected, THasManyParams>
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* The main fluent selection builder interface.
|
|
279
|
-
*
|
|
280
|
-
* @typeParam TEntity - The entity type being selected from
|
|
281
|
-
* @typeParam TSelected - Accumulated type of selected fields (grows with each selection)
|
|
282
|
-
* @typeParam THasManyParams - Record tracking has-many parameters for alias consistency
|
|
283
|
-
*
|
|
284
|
-
* @example
|
|
285
|
-
* ```ts
|
|
286
|
-
* // Select scalar fields
|
|
287
|
-
* e.id().title().content()
|
|
288
|
-
* // Type: { id: string, title: string, content: string }
|
|
289
|
-
*
|
|
290
|
-
* // Select with alias
|
|
291
|
-
* e.title({ as: 'headline' })
|
|
292
|
-
* // Type: { headline: string }
|
|
293
|
-
*
|
|
294
|
-
* // Select has-one relation
|
|
295
|
-
* e.author(a => a.name().email())
|
|
296
|
-
* // Type: { author: { name: string, email: string } }
|
|
297
|
-
*
|
|
298
|
-
* // Select has-many with options
|
|
299
|
-
* e.tags({ filter: { active: true } }, t => t.name())
|
|
300
|
-
* // Type: { tags: { name: string }[] }
|
|
301
|
-
* ```
|
|
302
|
-
*/
|
|
303
|
-
export type SelectionBuilder<TEntity, TSelected extends object = object, THasManyParams extends object = object> =
|
|
304
|
-
SelectionBuilderMethods<TEntity, TSelected, THasManyParams> & {
|
|
305
|
-
[SELECTION_META]: SelectionMeta
|
|
306
|
-
/** Type brand for the selected result */
|
|
307
|
-
readonly __selected: TSelected
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Extracts the selected type from a SelectionBuilder
|
|
312
|
-
*/
|
|
313
|
-
export type InferSelection<T> = T extends SelectionBuilder<infer _E, infer S, infer _P> ? S : never
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Type for the fluent definer function used in useEntity/useEntityList
|
|
317
|
-
*/
|
|
318
|
-
export type FluentDefiner<TModel, TResult extends object> = (
|
|
319
|
-
builder: SelectionBuilder<TModel>,
|
|
320
|
-
) => SelectionBuilder<TModel, TResult, object>
|
|
1
|
+
export {
|
|
2
|
+
SELECTION_META,
|
|
3
|
+
type SelectionBuilder,
|
|
4
|
+
type SelectionMeta,
|
|
5
|
+
type SelectionFieldMeta,
|
|
6
|
+
type FluentFragment,
|
|
7
|
+
type FluentDefiner,
|
|
8
|
+
type HasManyOptions,
|
|
9
|
+
type InferSelection,
|
|
10
|
+
type ScalarMethod,
|
|
11
|
+
type HasOneMethod,
|
|
12
|
+
type HasManyMethod,
|
|
13
|
+
} from '@contember/bindx-client'
|
|
@@ -1,56 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generates an alias for a has-many relation based on field name and parameters.
|
|
5
|
-
*
|
|
6
|
-
* If no parameters are provided or all are undefined, returns the fieldName as-is.
|
|
7
|
-
* Otherwise, generates a deterministic alias by hashing the parameters.
|
|
8
|
-
*
|
|
9
|
-
* @param fieldName - The original field name
|
|
10
|
-
* @param params - Optional has-many parameters (filter, orderBy, limit, offset)
|
|
11
|
-
* @returns The alias to use for this has-many relation
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* // No params - returns fieldName
|
|
16
|
-
* generateHasManyAlias('tags') // => 'tags'
|
|
17
|
-
*
|
|
18
|
-
* // With filter - generates unique alias
|
|
19
|
-
* generateHasManyAlias('tags', { filter: { active: true } }) // => 'tags_a7x9k2'
|
|
20
|
-
*
|
|
21
|
-
* // Different params - different aliases
|
|
22
|
-
* generateHasManyAlias('tags', { filter: { active: false } }) // => 'tags_b3m1p8'
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export function generateHasManyAlias(fieldName: string, params?: HasManyParams): string {
|
|
26
|
-
if (!params) {
|
|
27
|
-
return fieldName
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const { filter, orderBy, limit, offset } = params
|
|
31
|
-
|
|
32
|
-
// If all params are undefined, return fieldName
|
|
33
|
-
if (filter === undefined && orderBy === undefined && limit === undefined && offset === undefined) {
|
|
34
|
-
return fieldName
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Serialize parameters deterministically
|
|
38
|
-
const serialized = JSON.stringify({
|
|
39
|
-
f: filter,
|
|
40
|
-
o: orderBy,
|
|
41
|
-
l: limit,
|
|
42
|
-
s: offset,
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
// Simple djb2 hash algorithm
|
|
46
|
-
let hash = 5381
|
|
47
|
-
for (let i = 0; i < serialized.length; i++) {
|
|
48
|
-
hash = ((hash << 5) + hash) + serialized.charCodeAt(i)
|
|
49
|
-
hash = hash & hash // Convert to 32-bit integer
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Convert to base36 and take first 6 characters for compact representation
|
|
53
|
-
const hashStr = Math.abs(hash).toString(36).slice(0, 6)
|
|
54
|
-
|
|
55
|
-
return `${fieldName}_${hashStr}`
|
|
56
|
-
}
|
|
1
|
+
export { generateHasManyAlias } from '@contember/bindx-client'
|