simplesvelte 2.2.10 → 2.2.12
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/Select.svelte +63 -28
- package/dist/ag-grid-refactored.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -0
- package/dist/powerAppQuery.d.ts +398 -0
- package/dist/powerAppQuery.js +789 -0
- package/package.json +1 -1
- package/dist/ag-grid.d.ts +0 -551
- package/dist/ag-grid.js +0 -901
package/dist/Select.svelte
CHANGED
|
@@ -48,29 +48,42 @@
|
|
|
48
48
|
let detailsOpen = $state(false)
|
|
49
49
|
|
|
50
50
|
// Initialize value as array for multiple mode, ensure it's always an array when multiple
|
|
51
|
-
|
|
51
|
+
// Use derived to avoid timing issues with effects
|
|
52
|
+
let normalizedValue = $derived.by(() => {
|
|
52
53
|
if (multiple && !Array.isArray(value)) {
|
|
53
|
-
|
|
54
|
+
return value ? [value] : []
|
|
54
55
|
} else if (!multiple && Array.isArray(value)) {
|
|
55
|
-
|
|
56
|
+
return value.length > 0 ? value[0] : undefined
|
|
57
|
+
}
|
|
58
|
+
return value
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// Sync normalized value back to value prop when it differs
|
|
62
|
+
$effect(() => {
|
|
63
|
+
if (normalizedValue !== value) {
|
|
64
|
+
value = normalizedValue
|
|
56
65
|
}
|
|
57
66
|
})
|
|
58
67
|
|
|
59
68
|
// For single select mode
|
|
60
69
|
let selectedItem = $derived.by(() => {
|
|
61
70
|
if (multiple) return null
|
|
62
|
-
|
|
71
|
+
const currentValue = normalizedValue
|
|
72
|
+
return items.find((item) => item.value === currentValue)
|
|
63
73
|
})
|
|
64
74
|
// For multi select mode
|
|
65
75
|
let selectedItems = $derived.by(() => {
|
|
66
|
-
if (!multiple
|
|
67
|
-
|
|
76
|
+
if (!multiple) return []
|
|
77
|
+
const currentValue = normalizedValue
|
|
78
|
+
if (!Array.isArray(currentValue)) return []
|
|
79
|
+
return items.filter((item) => currentValue.includes(item.value))
|
|
68
80
|
})
|
|
69
81
|
|
|
70
82
|
// Check if an item is selected in multi-select mode
|
|
71
83
|
function isItemSelected(itemValue: any): boolean {
|
|
72
|
-
if (!multiple) return itemValue ===
|
|
73
|
-
|
|
84
|
+
if (!multiple) return itemValue === normalizedValue
|
|
85
|
+
const currentValue = normalizedValue
|
|
86
|
+
return Array.isArray(currentValue) && currentValue.includes(itemValue)
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
// Toggle item selection in multi-select mode
|
|
@@ -79,6 +92,7 @@
|
|
|
79
92
|
// Close dropdown and update filter immediately
|
|
80
93
|
filter = items.find((item) => item.value === itemValue)?.label || ''
|
|
81
94
|
detailsOpen = false
|
|
95
|
+
filterMode = 'auto'
|
|
82
96
|
|
|
83
97
|
// Wait for DOM update so details closes properly
|
|
84
98
|
await tick()
|
|
@@ -90,20 +104,22 @@
|
|
|
90
104
|
return
|
|
91
105
|
}
|
|
92
106
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
// For multiple selection, work with current array state
|
|
108
|
+
const currentValue = Array.isArray(normalizedValue) ? normalizedValue : []
|
|
109
|
+
|
|
110
|
+
if (currentValue.includes(itemValue)) {
|
|
111
|
+
value = currentValue.filter((v) => v !== itemValue)
|
|
97
112
|
} else {
|
|
98
|
-
value = [...
|
|
113
|
+
value = [...currentValue, itemValue]
|
|
99
114
|
}
|
|
100
115
|
if (onchange) onchange(value)
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
// Remove specific item from multi-select
|
|
104
119
|
function removeSelectedItem(itemValue: any) {
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
const currentValue = normalizedValue
|
|
121
|
+
if (Array.isArray(currentValue)) {
|
|
122
|
+
value = currentValue.filter((v) => v !== itemValue)
|
|
107
123
|
if (onchange) onchange(value)
|
|
108
124
|
}
|
|
109
125
|
}
|
|
@@ -117,16 +133,31 @@
|
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
let filter = $state('')
|
|
136
|
+
let filterMode = $state<'user' | 'auto'>('user') // Track if filter is user-controlled or auto-synced
|
|
120
137
|
|
|
121
|
-
//
|
|
138
|
+
// Auto-sync filter for single select when not user-controlled
|
|
122
139
|
$effect(() => {
|
|
123
|
-
if (!multiple &&
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
140
|
+
if (!multiple && !detailsOpen && filterMode === 'auto') {
|
|
141
|
+
if (selectedItem) {
|
|
142
|
+
filter = selectedItem.label
|
|
143
|
+
} else {
|
|
144
|
+
filter = ''
|
|
145
|
+
}
|
|
127
146
|
}
|
|
128
147
|
})
|
|
129
148
|
|
|
149
|
+
// Reset filter mode when user starts typing
|
|
150
|
+
function handleFilterInput() {
|
|
151
|
+
filterMode = 'user'
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Set filter mode to auto when closing dropdown
|
|
155
|
+
function handleDropdownClose() {
|
|
156
|
+
if (!multiple) {
|
|
157
|
+
filterMode = 'auto'
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
130
161
|
let filteredItems = $derived.by(() => {
|
|
131
162
|
if (filter.length === 0) return items
|
|
132
163
|
return items.filter((item) => item.label.toLowerCase().includes(filter.toLowerCase()))
|
|
@@ -247,12 +278,12 @@
|
|
|
247
278
|
</script>
|
|
248
279
|
|
|
249
280
|
<!-- Data inputs for form submission -->
|
|
250
|
-
{#if multiple && Array.isArray(
|
|
251
|
-
{#each
|
|
281
|
+
{#if multiple && Array.isArray(normalizedValue)}
|
|
282
|
+
{#each normalizedValue as val, i (val + '-' + i)}
|
|
252
283
|
<input type="hidden" {name} value={val} />
|
|
253
284
|
{/each}
|
|
254
|
-
{:else if !multiple &&
|
|
255
|
-
<input type="hidden" {name} {
|
|
285
|
+
{:else if !multiple && normalizedValue !== undefined && normalizedValue !== null && normalizedValue !== ''}
|
|
286
|
+
<input type="hidden" {name} value={normalizedValue} />
|
|
256
287
|
{/if}
|
|
257
288
|
|
|
258
289
|
<Label {label} {name} optional={!required} class={className} error={errorText}>
|
|
@@ -269,12 +300,14 @@
|
|
|
269
300
|
}
|
|
270
301
|
console.log('clickOutside')
|
|
271
302
|
detailsOpen = false
|
|
303
|
+
handleDropdownClose()
|
|
272
304
|
}}>
|
|
273
305
|
<summary
|
|
274
306
|
class="select h-max min-h-10 w-full min-w-12 cursor-pointer !bg-none pr-1"
|
|
275
307
|
onclick={() => {
|
|
276
308
|
searchEL?.focus()
|
|
277
309
|
filter = ''
|
|
310
|
+
filterMode = 'user'
|
|
278
311
|
}}>
|
|
279
312
|
{#if multiple}
|
|
280
313
|
<!-- Multi-select display with chips -->
|
|
@@ -299,11 +332,12 @@
|
|
|
299
332
|
class="h-full outline-0 {detailsOpen ? 'cursor-text' : 'cursor-pointer'}"
|
|
300
333
|
bind:this={searchEL}
|
|
301
334
|
bind:value={filter}
|
|
335
|
+
oninput={handleFilterInput}
|
|
302
336
|
onclick={() => {
|
|
303
337
|
detailsOpen = true
|
|
304
338
|
}}
|
|
305
339
|
placeholder="Search..."
|
|
306
|
-
required={required && (!Array.isArray(
|
|
340
|
+
required={required && (!Array.isArray(normalizedValue) || normalizedValue.length === 0)} />
|
|
307
341
|
</div>
|
|
308
342
|
{:else}
|
|
309
343
|
<!-- Single-select display -->
|
|
@@ -312,14 +346,15 @@
|
|
|
312
346
|
class="h-full w-full outline-0 {detailsOpen ? 'cursor-text' : 'cursor-pointer'}"
|
|
313
347
|
bind:this={searchEL}
|
|
314
348
|
bind:value={filter}
|
|
349
|
+
oninput={handleFilterInput}
|
|
315
350
|
onclick={() => {
|
|
316
351
|
detailsOpen = true
|
|
317
352
|
}}
|
|
318
353
|
placeholder={displayText}
|
|
319
|
-
required={required && !
|
|
354
|
+
required={required && !normalizedValue} />
|
|
320
355
|
{/if}
|
|
321
356
|
|
|
322
|
-
{#if !required && ((multiple && Array.isArray(
|
|
357
|
+
{#if !required && ((multiple && Array.isArray(normalizedValue) && normalizedValue.length > 0) || (!multiple && normalizedValue))}
|
|
323
358
|
<button
|
|
324
359
|
type="button"
|
|
325
360
|
class="btn btn-sm btn-circle btn-ghost absolute top-1 right-1"
|
|
@@ -370,7 +405,7 @@
|
|
|
370
405
|
{/if}
|
|
371
406
|
|
|
372
407
|
<!-- Render only visible items (headers and options) -->
|
|
373
|
-
{#each visibleItems.items as entry (entry.type === 'header' ? 'header-' + entry.group : entry.item.value)}
|
|
408
|
+
{#each visibleItems.items as entry, idx (entry.type === 'header' ? 'header-' + entry.group + '-' + idx : 'option-' + entry.item.value + '-' + idx)}
|
|
374
409
|
{#if entry.type === 'header'}
|
|
375
410
|
<li
|
|
376
411
|
class="bg-base-200 top-0 z-10 flex items-center justify-center px-2 text-lg font-bold text-gray-700"
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export { default as Modal } from './Modal.svelte';
|
|
|
6
6
|
export { default as Grid } from './Grid.svelte';
|
|
7
7
|
export { Pop } from './pop.js';
|
|
8
8
|
export { clickOutside, FormHelper, RoleHelper as roleHelper, formatDate } from './utils.js';
|
|
9
|
-
export { createAGGridQuery, createAGGridDatasource, type AGGridRequest, type AGGridResponse, type ComputedField, type AGGridQueryConfig, agGridRequestSchema, defaultSSRMColDef, defaultSSRMGridOptions, filterConfigs, } from './ag-grid-refactored.js';
|
|
9
|
+
export { createAGGridQuery, createAGGridDatasource, saveParams, fetchParams, type AGGridRequest, type AGGridResponse, type ComputedField, type AGGridQueryConfig, agGridRequestSchema, defaultAGGridRequest, defaultSSRMColDef, defaultSSRMGridOptions, filterConfigs, } from './ag-grid-refactored.js';
|
|
10
10
|
import './styles.css';
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,12 @@ export { clickOutside, FormHelper, RoleHelper as roleHelper, formatDate } from '
|
|
|
10
10
|
export {
|
|
11
11
|
// Main functions
|
|
12
12
|
createAGGridQuery, createAGGridDatasource,
|
|
13
|
+
// Parameter persistence functions
|
|
14
|
+
saveParams, fetchParams,
|
|
13
15
|
// Zod schema
|
|
14
16
|
agGridRequestSchema,
|
|
17
|
+
// Default request
|
|
18
|
+
defaultAGGridRequest,
|
|
15
19
|
// Config helpers
|
|
16
20
|
defaultSSRMColDef, defaultSSRMGridOptions, filterConfigs, } from './ag-grid-refactored.js';
|
|
17
21
|
// Export CSS for consumers
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import type { AGGridRequest, AGGridResponse } from './ag-grid-refactored.js';
|
|
2
|
+
/**
|
|
3
|
+
* AG Grid sort model (from AG Grid API)
|
|
4
|
+
*/
|
|
5
|
+
type AGGridSort = {
|
|
6
|
+
colId: string;
|
|
7
|
+
sort: 'asc' | 'desc';
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Power Apps Web API OData response format
|
|
11
|
+
*/
|
|
12
|
+
export type PowerAppsODataResponse<TEntity = any> = {
|
|
13
|
+
'@odata.context': string;
|
|
14
|
+
'@odata.count'?: number;
|
|
15
|
+
'@odata.nextLink'?: string;
|
|
16
|
+
value: TEntity[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Power Apps Web API error response format
|
|
20
|
+
*/
|
|
21
|
+
export type PowerAppsError = {
|
|
22
|
+
error: {
|
|
23
|
+
code: string;
|
|
24
|
+
message: string;
|
|
25
|
+
innererror?: {
|
|
26
|
+
message: string;
|
|
27
|
+
type: string;
|
|
28
|
+
stacktrace: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for Power Apps query builder
|
|
34
|
+
*/
|
|
35
|
+
export type PowerAppsQueryConfig<TEntity = any> = {
|
|
36
|
+
/** Base URL for the Web API (e.g., "[Organization URI]/api/data/v9.2") */
|
|
37
|
+
baseUrl: string;
|
|
38
|
+
/** Entity set name (e.g., "accounts", "contacts") */
|
|
39
|
+
entitySet: string;
|
|
40
|
+
/** Optional: HTTP headers (auth, preferences, etc.) */
|
|
41
|
+
headers?: Record<string, string>;
|
|
42
|
+
/** Optional: Default columns to select */
|
|
43
|
+
defaultSelect?: string[];
|
|
44
|
+
/** Optional: Default sort order */
|
|
45
|
+
defaultOrderBy?: string;
|
|
46
|
+
/** Optional: Related entities to expand (simple strings or full ExpandConfig objects) */
|
|
47
|
+
expand?: (string | ExpandConfig)[];
|
|
48
|
+
/** Optional: Transform OData response to custom format */
|
|
49
|
+
transformResponse?: (data: TEntity[]) => TEntity[];
|
|
50
|
+
/** Optional: Maximum URL length before warning (default: 32768) */
|
|
51
|
+
maxUrlLength?: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* OData query parameters
|
|
55
|
+
*/
|
|
56
|
+
export type ODataQueryParams = {
|
|
57
|
+
$select?: string;
|
|
58
|
+
$filter?: string;
|
|
59
|
+
$orderby?: string;
|
|
60
|
+
$top?: number;
|
|
61
|
+
$skip?: number;
|
|
62
|
+
$count?: boolean;
|
|
63
|
+
$expand?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Builds the OData $select query parameter from column selections
|
|
67
|
+
*
|
|
68
|
+
* @param columns - Array of column names to select
|
|
69
|
+
* @returns OData $select string (e.g., "name,revenue,statecode")
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* buildODataSelect(['accountid', 'name', 'revenue'])
|
|
74
|
+
* // Returns: "accountid,name,revenue"
|
|
75
|
+
*
|
|
76
|
+
* buildODataSelect(['contactid', 'fullname', 'parentcustomerid_account/name'])
|
|
77
|
+
* // Returns: "contactid,fullname,parentcustomerid_account/name"
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function buildODataSelect(columns?: string[]): string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Builds the OData $orderby query parameter from AG Grid sort model
|
|
83
|
+
*
|
|
84
|
+
* OData orderby syntax: "field1 asc,field2 desc"
|
|
85
|
+
*
|
|
86
|
+
* @param sortModel - AG Grid sort model
|
|
87
|
+
* @param defaultOrderBy - Fallback sort if no sort model provided
|
|
88
|
+
* @returns OData $orderby string (e.g., "name asc,revenue desc")
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* buildODataOrderBy([
|
|
93
|
+
* { colId: 'name', sort: 'asc' },
|
|
94
|
+
* { colId: 'revenue', sort: 'desc' }
|
|
95
|
+
* ])
|
|
96
|
+
* // Returns: "name asc,revenue desc"
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function buildODataOrderBy(sortModel?: AGGridSort[], defaultOrderBy?: string): string | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* Builds the OData $filter query parameter from AG Grid filter model
|
|
102
|
+
*
|
|
103
|
+
* Converts AG Grid's filter model to OData filter syntax, supporting:
|
|
104
|
+
* - Text filters: eq, ne, contains, startswith, endswith
|
|
105
|
+
* - Number filters: eq, ne, gt, ge, lt, le, inRange
|
|
106
|
+
* - Date filters: eq, ne, gt, ge, lt, le, inRange
|
|
107
|
+
* - Set filters: multi-value OR conditions
|
|
108
|
+
* - Null checks: blank/notBlank
|
|
109
|
+
*
|
|
110
|
+
* @param filterModel - AG Grid filter model
|
|
111
|
+
* @returns OData $filter string
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* // Text filter
|
|
116
|
+
* buildODataFilter({ name: { filterType: 'text', type: 'contains', filter: 'John' } })
|
|
117
|
+
* // Returns: "contains(name,'John')"
|
|
118
|
+
*
|
|
119
|
+
* // Number range
|
|
120
|
+
* buildODataFilter({
|
|
121
|
+
* revenue: { filterType: 'number', type: 'inRange', filter: 1000, filterTo: 5000 }
|
|
122
|
+
* })
|
|
123
|
+
* // Returns: "revenue ge 1000 and revenue le 5000"
|
|
124
|
+
*
|
|
125
|
+
* // Multiple filters (AND logic)
|
|
126
|
+
* buildODataFilter({
|
|
127
|
+
* name: { filterType: 'text', type: 'contains', filter: 'Corp' },
|
|
128
|
+
* revenue: { filterType: 'number', type: 'greaterThan', filter: 10000 }
|
|
129
|
+
* })
|
|
130
|
+
* // Returns: "contains(name,'Corp') and revenue gt 10000"
|
|
131
|
+
*
|
|
132
|
+
* // Set filter (OR logic for multiple values)
|
|
133
|
+
* buildODataFilter({
|
|
134
|
+
* status: { filterType: 'set', values: ['Active', 'Pending'] }
|
|
135
|
+
* })
|
|
136
|
+
* // Returns: "(status eq 'Active' or status eq 'Pending')"
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function buildODataFilter(filterModel?: Record<string, unknown>): string | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Configuration for expanding a related entity
|
|
142
|
+
*/
|
|
143
|
+
export type ExpandConfig = {
|
|
144
|
+
/** Navigation property name to expand */
|
|
145
|
+
navigationProperty: string;
|
|
146
|
+
/** Optional: Columns to select from the expanded entity */
|
|
147
|
+
select?: string[];
|
|
148
|
+
/** Optional: Filter for collection-valued navigation properties */
|
|
149
|
+
filter?: string;
|
|
150
|
+
/** Optional: Order by for collection-valued navigation properties (not supported with nested expand) */
|
|
151
|
+
orderBy?: string;
|
|
152
|
+
/** Optional: Top N records for collection-valued navigation properties (not supported with nested expand) */
|
|
153
|
+
top?: number;
|
|
154
|
+
/** Optional: Nested expands */
|
|
155
|
+
expand?: ExpandConfig[];
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Builds the OData $expand query parameter for joining related tables
|
|
159
|
+
*
|
|
160
|
+
* Supports:
|
|
161
|
+
* - Single-valued navigation properties (many-to-one lookups)
|
|
162
|
+
* - Collection-valued navigation properties (one-to-many relationships)
|
|
163
|
+
* - Nested expands (up to recommended limit)
|
|
164
|
+
* - Expand with $select, $filter, $orderby, $top
|
|
165
|
+
*
|
|
166
|
+
* Limitations:
|
|
167
|
+
* - Max 15 $expand options recommended per query
|
|
168
|
+
* - $orderby and $top not supported with nested $expand on collections
|
|
169
|
+
* - Nested $expand not supported with N:N relationships
|
|
170
|
+
*
|
|
171
|
+
* @param expands - Array of expand configurations
|
|
172
|
+
* @returns OData $expand string
|
|
173
|
+
*
|
|
174
|
+
* @example Single expand with select
|
|
175
|
+
* ```typescript
|
|
176
|
+
* buildODataExpand([
|
|
177
|
+
* { navigationProperty: 'primarycontactid', select: ['fullname', 'emailaddress1'] }
|
|
178
|
+
* ])
|
|
179
|
+
* // Returns: "primarycontactid($select=fullname,emailaddress1)"
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @example Multiple expands
|
|
183
|
+
* ```typescript
|
|
184
|
+
* buildODataExpand([
|
|
185
|
+
* { navigationProperty: 'primarycontactid', select: ['fullname'] },
|
|
186
|
+
* { navigationProperty: 'createdby', select: ['fullname'] }
|
|
187
|
+
* ])
|
|
188
|
+
* // Returns: "primarycontactid($select=fullname),createdby($select=fullname)"
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @example Collection with filter and order
|
|
192
|
+
* ```typescript
|
|
193
|
+
* buildODataExpand([
|
|
194
|
+
* {
|
|
195
|
+
* navigationProperty: 'Account_Tasks',
|
|
196
|
+
* select: ['subject', 'createdon'],
|
|
197
|
+
* filter: "contains(subject,'Task')",
|
|
198
|
+
* orderBy: 'createdon desc',
|
|
199
|
+
* top: 10
|
|
200
|
+
* }
|
|
201
|
+
* ])
|
|
202
|
+
* // Returns: "Account_Tasks($select=subject,createdon;$filter=contains(subject,'Task');$orderby=createdon desc;$top=10)"
|
|
203
|
+
* ```
|
|
204
|
+
*
|
|
205
|
+
* @example Nested expand
|
|
206
|
+
* ```typescript
|
|
207
|
+
* buildODataExpand([
|
|
208
|
+
* {
|
|
209
|
+
* navigationProperty: 'primarycontactid',
|
|
210
|
+
* select: ['fullname'],
|
|
211
|
+
* expand: [
|
|
212
|
+
* { navigationProperty: 'createdby', select: ['fullname'] }
|
|
213
|
+
* ]
|
|
214
|
+
* }
|
|
215
|
+
* ])
|
|
216
|
+
* // Returns: "primarycontactid($select=fullname;$expand=createdby($select=fullname))"
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
export declare function buildODataExpand(expands?: ExpandConfig[]): string | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* Simplified expand builder for basic use cases
|
|
222
|
+
* Use this when you just need to expand navigation properties with optional column selection
|
|
223
|
+
*
|
|
224
|
+
* @param navigationProperties - Array of navigation property names or objects with select
|
|
225
|
+
* @returns OData $expand string
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```typescript
|
|
229
|
+
* buildSimpleExpand(['primarycontactid', 'createdby'])
|
|
230
|
+
* // Returns: "primarycontactid,createdby"
|
|
231
|
+
*
|
|
232
|
+
* buildSimpleExpand([
|
|
233
|
+
* 'primarycontactid',
|
|
234
|
+
* { navigationProperty: 'createdby', select: ['fullname'] }
|
|
235
|
+
* ])
|
|
236
|
+
* // Returns: "primarycontactid,createdby($select=fullname)"
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
export declare function buildSimpleExpand(navigationProperties?: (string | {
|
|
240
|
+
navigationProperty: string;
|
|
241
|
+
select?: string[];
|
|
242
|
+
})[]): string | undefined;
|
|
243
|
+
/**
|
|
244
|
+
* Creates a Power Apps query handler for server-side data fetching
|
|
245
|
+
*
|
|
246
|
+
* This is the main API for querying Power Apps Web API. It accepts AG Grid requests
|
|
247
|
+
* and returns data in AG Grid response format, handling all OData translation automatically.
|
|
248
|
+
*
|
|
249
|
+
* @param config - Power Apps query configuration
|
|
250
|
+
* @returns Function that processes AG Grid requests and returns responses
|
|
251
|
+
*
|
|
252
|
+
* @example Basic usage
|
|
253
|
+
* ```typescript
|
|
254
|
+
* const accountsQuery = createPowerAppsQuery({
|
|
255
|
+
* baseUrl: 'https://org.crm.dynamics.com/api/data/v9.2',
|
|
256
|
+
* entitySet: 'accounts',
|
|
257
|
+
* headers: {
|
|
258
|
+
* 'Authorization': 'Bearer YOUR_TOKEN',
|
|
259
|
+
* 'Prefer': 'odata.include-annotations="*"'
|
|
260
|
+
* },
|
|
261
|
+
* defaultSelect: ['accountid', 'name', 'revenue']
|
|
262
|
+
* })
|
|
263
|
+
*
|
|
264
|
+
* const response = await accountsQuery(agGridRequest)
|
|
265
|
+
* // Returns: { rows: [...], lastRow: 1000 }
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @example With related data
|
|
269
|
+
* ```typescript
|
|
270
|
+
* const contactsQuery = createPowerAppsQuery({
|
|
271
|
+
* baseUrl: 'https://org.crm.dynamics.com/api/data/v9.2',
|
|
272
|
+
* entitySet: 'contacts',
|
|
273
|
+
* expand: [
|
|
274
|
+
* { navigationProperty: 'parentcustomerid_account', select: ['name'] }
|
|
275
|
+
* ]
|
|
276
|
+
* })
|
|
277
|
+
* ```
|
|
278
|
+
*
|
|
279
|
+
* @example With transformation
|
|
280
|
+
* ```typescript
|
|
281
|
+
* const query = createPowerAppsQuery({
|
|
282
|
+
* baseUrl: 'https://org.crm.dynamics.com/api/data/v9.2',
|
|
283
|
+
* entitySet: 'accounts',
|
|
284
|
+
* transformResponse: (data) => data.map(item => ({
|
|
285
|
+
* id: item.accountid,
|
|
286
|
+
* name: item.name
|
|
287
|
+
* }))
|
|
288
|
+
* })
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
export declare function createPowerAppsQuery<TEntity = any>(config: PowerAppsQueryConfig<TEntity>): (request: AGGridRequest) => Promise<AGGridResponse<TEntity>>;
|
|
292
|
+
/**
|
|
293
|
+
* Fetches the next page using the @odata.nextLink URL
|
|
294
|
+
*
|
|
295
|
+
* Use this to implement manual pagination when you need to fetch additional pages
|
|
296
|
+
* beyond what AG Grid requests automatically.
|
|
297
|
+
*
|
|
298
|
+
* @param nextLink - The @odata.nextLink URL from a previous response
|
|
299
|
+
* @param headers - Headers to include in the request (auth, etc.)
|
|
300
|
+
* @returns The next page of data
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```typescript
|
|
304
|
+
* const firstPage = await accountsQuery(agGridRequest)
|
|
305
|
+
*
|
|
306
|
+
* // If there's more data, fetch the next page
|
|
307
|
+
* if (firstPage.nextLink) {
|
|
308
|
+
* const secondPage = await fetchNextPage(firstPage.nextLink, {
|
|
309
|
+
* 'Authorization': 'Bearer YOUR_TOKEN'
|
|
310
|
+
* })
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
export declare function fetchNextPage<TEntity = any>(nextLink: string, headers?: Record<string, string>): Promise<PowerAppsODataResponse<TEntity>>;
|
|
315
|
+
/**
|
|
316
|
+
* Extended response type that includes pagination information
|
|
317
|
+
*/
|
|
318
|
+
export type PowerAppsQueryResult<TEntity = any> = AGGridResponse<TEntity> & {
|
|
319
|
+
/** Next page link if more data available */
|
|
320
|
+
nextLink?: string;
|
|
321
|
+
/** Total count of records matching the filter */
|
|
322
|
+
totalCount?: number;
|
|
323
|
+
/** Raw OData context information */
|
|
324
|
+
odataContext?: string;
|
|
325
|
+
};
|
|
326
|
+
/**
|
|
327
|
+
* Enhanced query function that returns additional metadata
|
|
328
|
+
*
|
|
329
|
+
* Use this when you need access to pagination links and other OData metadata
|
|
330
|
+
*
|
|
331
|
+
* @param config - Power Apps query configuration
|
|
332
|
+
* @returns Function that processes requests and returns enhanced responses
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```typescript
|
|
336
|
+
* const query = createPowerAppsQueryWithMetadata({
|
|
337
|
+
* baseUrl: 'https://org.crm.dynamics.com/api/data/v9.2',
|
|
338
|
+
* entitySet: 'accounts'
|
|
339
|
+
* })
|
|
340
|
+
*
|
|
341
|
+
* const result = await query(agGridRequest)
|
|
342
|
+
* console.log(`Got ${result.rows.length} rows, total: ${result.totalCount}`)
|
|
343
|
+
*
|
|
344
|
+
* if (result.nextLink) {
|
|
345
|
+
* console.log('More data available at:', result.nextLink)
|
|
346
|
+
* }
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
export declare function createPowerAppsQueryWithMetadata<TEntity = any>(config: PowerAppsQueryConfig<TEntity>): (request: AGGridRequest) => Promise<PowerAppsQueryResult<TEntity>>;
|
|
350
|
+
/**
|
|
351
|
+
* Utility to fetch all pages of data (use with caution for large datasets)
|
|
352
|
+
*
|
|
353
|
+
* This will continue fetching pages until no more data is available.
|
|
354
|
+
* Be careful with large datasets as this can consume significant memory and time.
|
|
355
|
+
*
|
|
356
|
+
* @param queryFn - The query function created by createPowerAppsQueryWithMetadata
|
|
357
|
+
* @param request - Initial AG Grid request
|
|
358
|
+
* @param maxPages - Optional limit on number of pages to fetch (default: unlimited)
|
|
359
|
+
* @returns All rows across all pages
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* const query = createPowerAppsQueryWithMetadata({
|
|
364
|
+
* baseUrl: 'https://org.crm.dynamics.com/api/data/v9.2',
|
|
365
|
+
* entitySet: 'accounts'
|
|
366
|
+
* })
|
|
367
|
+
*
|
|
368
|
+
* // Fetch up to 10 pages (1000 records if pageSize is 100)
|
|
369
|
+
* const allData = await fetchAllPages(query, agGridRequest, 10)
|
|
370
|
+
* console.log(`Fetched ${allData.length} total records`)
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
export declare function fetchAllPages<TEntity = any>(queryFn: (request: AGGridRequest) => Promise<PowerAppsQueryResult<TEntity>>, request: AGGridRequest, maxPages?: number): Promise<TEntity[]>;
|
|
374
|
+
export {};
|
|
375
|
+
/**
|
|
376
|
+
* Main exports:
|
|
377
|
+
*
|
|
378
|
+
* Query Builders:
|
|
379
|
+
* - createPowerAppsQuery() - Main query function (returns AG Grid format)
|
|
380
|
+
* - createPowerAppsQueryWithMetadata() - Enhanced query with pagination metadata
|
|
381
|
+
*
|
|
382
|
+
* Helper Functions:
|
|
383
|
+
* - buildODataSelect() - Build $select clause
|
|
384
|
+
* - buildODataOrderBy() - Build $orderby clause
|
|
385
|
+
* - buildODataFilter() - Build $filter clause (from AG Grid filters)
|
|
386
|
+
* - buildODataExpand() - Build $expand clause
|
|
387
|
+
* - buildSimpleExpand() - Simplified expand builder
|
|
388
|
+
* - fetchNextPage() - Fetch next page using @odata.nextLink
|
|
389
|
+
* - fetchAllPages() - Fetch all pages (use with caution)
|
|
390
|
+
*
|
|
391
|
+
* Types:
|
|
392
|
+
* - PowerAppsQueryConfig - Configuration for query builder
|
|
393
|
+
* - PowerAppsODataResponse - OData response format
|
|
394
|
+
* - PowerAppsError - Error response format
|
|
395
|
+
* - PowerAppsQueryResult - Enhanced response with metadata
|
|
396
|
+
* - ExpandConfig - Configuration for expanding related entities
|
|
397
|
+
* - ODataQueryParams - OData query parameters
|
|
398
|
+
*/
|