@object-ui/data-objectstack 3.1.5 → 3.3.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/CHANGELOG.md +118 -0
- package/README.md +20 -1
- package/dist/index.cjs +176 -33
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +174 -33
- package/package.json +34 -9
- package/src/aggregate.test.ts +277 -0
- package/src/cache/MetadataCache.test.ts +51 -0
- package/src/cache/MetadataCache.ts +37 -8
- package/src/connection.test.ts +55 -8
- package/src/errors.ts +2 -2
- package/src/index.ts +128 -24
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @object-ui/data-objectstack
|
|
2
|
+
|
|
3
|
+
## 3.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @object-ui/types@3.3.1
|
|
8
|
+
- @object-ui/core@3.3.1
|
|
9
|
+
|
|
10
|
+
## 3.3.0
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- @object-ui/types@3.3.0
|
|
15
|
+
- @object-ui/core@3.3.0
|
|
16
|
+
|
|
17
|
+
## 3.2.0
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- @object-ui/types@3.2.0
|
|
22
|
+
- @object-ui/core@3.2.0
|
|
23
|
+
|
|
24
|
+
## 3.1.5
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- @object-ui/types@3.1.5
|
|
29
|
+
- @object-ui/core@3.1.5
|
|
30
|
+
|
|
31
|
+
## 3.1.4
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- @object-ui/types@3.1.4
|
|
36
|
+
- @object-ui/core@3.1.4
|
|
37
|
+
|
|
38
|
+
## 3.1.3
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- @object-ui/types@3.1.3
|
|
43
|
+
- @object-ui/core@3.1.3
|
|
44
|
+
|
|
45
|
+
## 3.1.2
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- @object-ui/types@3.1.2
|
|
50
|
+
- @object-ui/core@3.1.2
|
|
51
|
+
|
|
52
|
+
## 3.1.1
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- Updated dependencies
|
|
57
|
+
- @object-ui/types@3.1.1
|
|
58
|
+
- @object-ui/core@3.1.1
|
|
59
|
+
|
|
60
|
+
## 3.0.3
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- @object-ui/types@3.0.3
|
|
65
|
+
- @object-ui/core@3.0.3
|
|
66
|
+
|
|
67
|
+
## 3.0.2
|
|
68
|
+
|
|
69
|
+
### Patch Changes
|
|
70
|
+
|
|
71
|
+
- @object-ui/types@3.0.2
|
|
72
|
+
- @object-ui/core@3.0.2
|
|
73
|
+
|
|
74
|
+
## 3.0.1
|
|
75
|
+
|
|
76
|
+
### Patch Changes
|
|
77
|
+
|
|
78
|
+
- @object-ui/types@3.0.1
|
|
79
|
+
- @object-ui/core@3.0.1
|
|
80
|
+
|
|
81
|
+
## 3.0.0
|
|
82
|
+
|
|
83
|
+
### Minor Changes
|
|
84
|
+
|
|
85
|
+
- 87979c3: Upgrade to @objectstack v3.0.0 and console bundle optimization
|
|
86
|
+
- Upgraded all @objectstack/\* packages from ^2.0.7 to ^3.0.0
|
|
87
|
+
- Breaking change migrations: Hub → Cloud namespace, definePlugin removed, PaginatedResult.value → .records, PaginatedResult.count → .total, client.meta.getObject() → client.meta.getItem()
|
|
88
|
+
- Console bundle optimization: split monolithic 3.7 MB chunk into 17 granular cacheable chunks (95% main entry reduction)
|
|
89
|
+
- Added gzip + brotli pre-compression via vite-plugin-compression2
|
|
90
|
+
- Lazy MSW loading for build:server (~150 KB gzip saved)
|
|
91
|
+
- Added bundle analysis with rollup-plugin-visualizer
|
|
92
|
+
|
|
93
|
+
### Patch Changes
|
|
94
|
+
|
|
95
|
+
- Updated dependencies [87979c3]
|
|
96
|
+
- @object-ui/types@3.0.0
|
|
97
|
+
- @object-ui/core@3.0.0
|
|
98
|
+
|
|
99
|
+
## 2.0.0
|
|
100
|
+
|
|
101
|
+
### Major Changes
|
|
102
|
+
|
|
103
|
+
- b859617: Release v1.0.0 — unify all package versions to 1.0.0
|
|
104
|
+
|
|
105
|
+
### Patch Changes
|
|
106
|
+
|
|
107
|
+
- Updated dependencies [b859617]
|
|
108
|
+
- @object-ui/types@2.0.0
|
|
109
|
+
- @object-ui/core@2.0.0
|
|
110
|
+
|
|
111
|
+
## 0.3.1
|
|
112
|
+
|
|
113
|
+
### Patch Changes
|
|
114
|
+
|
|
115
|
+
- Maintenance release - Documentation and build improvements
|
|
116
|
+
- Updated dependencies
|
|
117
|
+
- @object-ui/types@0.3.1
|
|
118
|
+
- @object-ui/core@0.3.1
|
package/README.md
CHANGED
|
@@ -356,6 +356,25 @@ dataSource.clearCache();
|
|
|
356
356
|
dataSource.invalidateCache('users');
|
|
357
357
|
```
|
|
358
358
|
|
|
359
|
+
<!-- release-metadata:v3.3.0 -->
|
|
360
|
+
|
|
361
|
+
## Compatibility
|
|
362
|
+
|
|
363
|
+
- **Node.js:** ≥ 18
|
|
364
|
+
- **TypeScript:** ≥ 5.0 (strict mode)
|
|
365
|
+
- **`@objectstack/spec`:** ^3.3.0
|
|
366
|
+
- **`@objectstack/client`:** ^3.3.0
|
|
367
|
+
- **Tailwind CSS:** ≥ 3.4 (for packages with UI)
|
|
368
|
+
|
|
369
|
+
## Links
|
|
370
|
+
|
|
371
|
+
- 📚 [Documentation](https://www.objectui.org/docs/guide/data-source)
|
|
372
|
+
- 📦 [npm package](https://www.npmjs.com/package/@object-ui/data-objectstack)
|
|
373
|
+
- 📝 [Changelog](./CHANGELOG.md)
|
|
374
|
+
- 🐛 [Report an issue](https://github.com/objectstack-ai/objectui/issues)
|
|
375
|
+
- 🤝 [Contributing Guide](https://github.com/objectstack-ai/objectui/blob/main/CONTRIBUTING.md)
|
|
376
|
+
- 🗺️ [Roadmap](https://github.com/objectstack-ai/objectui/blob/main/ROADMAP.md)
|
|
377
|
+
|
|
359
378
|
## License
|
|
360
379
|
|
|
361
|
-
MIT
|
|
380
|
+
MIT — see [LICENSE](./LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -33,10 +33,12 @@ __export(index_exports, {
|
|
|
33
33
|
SecurityManager: () => SecurityManager,
|
|
34
34
|
ValidationError: () => ValidationError,
|
|
35
35
|
calculateAutoLayout: () => calculateAutoLayout,
|
|
36
|
+
clearSharedDiscoveryCache: () => clearSharedDiscoveryCache,
|
|
36
37
|
createDefaultCanvasConfig: () => createDefaultCanvasConfig,
|
|
37
38
|
createErrorFromResponse: () => createErrorFromResponse,
|
|
38
39
|
createObjectStackAdapter: () => createObjectStackAdapter,
|
|
39
40
|
generateContractManifest: () => generateContractManifest,
|
|
41
|
+
getSharedDiscovery: () => getSharedDiscovery,
|
|
40
42
|
isErrorType: () => isErrorType,
|
|
41
43
|
isObjectStackError: () => isObjectStackError,
|
|
42
44
|
snapToGrid: () => snapToGrid,
|
|
@@ -44,7 +46,72 @@ __export(index_exports, {
|
|
|
44
46
|
});
|
|
45
47
|
module.exports = __toCommonJS(index_exports);
|
|
46
48
|
var import_client = require("@objectstack/client");
|
|
47
|
-
|
|
49
|
+
|
|
50
|
+
// ../core/src/utils/filter-converter.ts
|
|
51
|
+
function convertOperatorToAST(operator) {
|
|
52
|
+
const operatorMap = {
|
|
53
|
+
"$eq": "=",
|
|
54
|
+
"$ne": "!=",
|
|
55
|
+
"$gt": ">",
|
|
56
|
+
"$gte": ">=",
|
|
57
|
+
"$lt": "<",
|
|
58
|
+
"$lte": "<=",
|
|
59
|
+
"$in": "in",
|
|
60
|
+
"$nin": "nin",
|
|
61
|
+
"$notin": "nin",
|
|
62
|
+
"$between": "between",
|
|
63
|
+
"$contains": "contains",
|
|
64
|
+
"$notContains": "notcontains",
|
|
65
|
+
"$notcontains": "notcontains",
|
|
66
|
+
"$startsWith": "startswith",
|
|
67
|
+
"$startswith": "startswith",
|
|
68
|
+
"$endsWith": "endswith",
|
|
69
|
+
"$endswith": "endswith"
|
|
70
|
+
};
|
|
71
|
+
return operatorMap[operator] || null;
|
|
72
|
+
}
|
|
73
|
+
function convertFiltersToAST(filter) {
|
|
74
|
+
const conditions = [];
|
|
75
|
+
for (const [field, value] of Object.entries(filter)) {
|
|
76
|
+
if (value === null || value === void 0) continue;
|
|
77
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
78
|
+
for (const [operator, operatorValue] of Object.entries(value)) {
|
|
79
|
+
if (operator === "$regex") {
|
|
80
|
+
console.warn(
|
|
81
|
+
`[ObjectUI] Warning: $regex operator is not fully supported. Converting to 'contains' which only supports substring matching, not regex patterns. Field: '${field}', Value: ${JSON.stringify(operatorValue)}. Consider using $contains or $startsWith instead.`
|
|
82
|
+
);
|
|
83
|
+
conditions.push([field, "contains", operatorValue]);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (operator === "$null") {
|
|
87
|
+
conditions.push([field, operatorValue ? "is_null" : "is_not_null", true]);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (operator === "$exists") {
|
|
91
|
+
conditions.push([field, operatorValue ? "is_not_null" : "is_null", true]);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const astOperator = convertOperatorToAST(operator);
|
|
95
|
+
if (astOperator) {
|
|
96
|
+
conditions.push([field, astOperator, operatorValue]);
|
|
97
|
+
} else {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`[ObjectUI] Unknown filter operator '${operator}' for field '${field}'. Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $between, $contains, $notContains, $startsWith, $endsWith, $null, $exists. If you need exact object matching, use the value directly without an operator.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
conditions.push([field, "=", value]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (conditions.length === 0) {
|
|
108
|
+
return filter;
|
|
109
|
+
}
|
|
110
|
+
if (conditions.length === 1) {
|
|
111
|
+
return conditions[0];
|
|
112
|
+
}
|
|
113
|
+
return ["and", ...conditions];
|
|
114
|
+
}
|
|
48
115
|
|
|
49
116
|
// src/cache/MetadataCache.ts
|
|
50
117
|
var MetadataCache = class {
|
|
@@ -57,16 +124,19 @@ var MetadataCache = class {
|
|
|
57
124
|
*/
|
|
58
125
|
constructor(options = {}) {
|
|
59
126
|
__publicField(this, "cache");
|
|
127
|
+
__publicField(this, "inflight");
|
|
60
128
|
__publicField(this, "maxSize");
|
|
61
129
|
__publicField(this, "ttl");
|
|
62
130
|
__publicField(this, "stats");
|
|
63
131
|
this.cache = /* @__PURE__ */ new Map();
|
|
132
|
+
this.inflight = /* @__PURE__ */ new Map();
|
|
64
133
|
this.maxSize = options.maxSize || 100;
|
|
65
134
|
this.ttl = options.ttl || 5 * 60 * 1e3;
|
|
66
135
|
this.stats = {
|
|
67
136
|
hits: 0,
|
|
68
137
|
misses: 0,
|
|
69
|
-
evictions: 0
|
|
138
|
+
evictions: 0,
|
|
139
|
+
coalesced: 0
|
|
70
140
|
};
|
|
71
141
|
}
|
|
72
142
|
/**
|
|
@@ -92,10 +162,31 @@ var MetadataCache = class {
|
|
|
92
162
|
this.cache.delete(key);
|
|
93
163
|
}
|
|
94
164
|
}
|
|
165
|
+
const existing = this.inflight.get(key);
|
|
166
|
+
if (existing) {
|
|
167
|
+
this.stats.coalesced++;
|
|
168
|
+
return existing;
|
|
169
|
+
}
|
|
95
170
|
this.stats.misses++;
|
|
96
|
-
const
|
|
171
|
+
const promise = (async () => {
|
|
172
|
+
try {
|
|
173
|
+
const data = await fetcher();
|
|
174
|
+
this.set(key, data);
|
|
175
|
+
return data;
|
|
176
|
+
} finally {
|
|
177
|
+
this.inflight.delete(key);
|
|
178
|
+
}
|
|
179
|
+
})();
|
|
180
|
+
this.inflight.set(key, promise);
|
|
181
|
+
return promise;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Prime the cache with a pre-fetched value. Useful when a bulk endpoint
|
|
185
|
+
* (e.g. list of all object schemas) returns data that would otherwise
|
|
186
|
+
* be fetched again per item.
|
|
187
|
+
*/
|
|
188
|
+
prime(key, data) {
|
|
97
189
|
this.set(key, data);
|
|
98
|
-
return data;
|
|
99
190
|
}
|
|
100
191
|
/**
|
|
101
192
|
* Set a value in the cache
|
|
@@ -142,10 +233,12 @@ var MetadataCache = class {
|
|
|
142
233
|
*/
|
|
143
234
|
clear() {
|
|
144
235
|
this.cache.clear();
|
|
236
|
+
this.inflight.clear();
|
|
145
237
|
this.stats = {
|
|
146
238
|
hits: 0,
|
|
147
239
|
misses: 0,
|
|
148
|
-
evictions: 0
|
|
240
|
+
evictions: 0,
|
|
241
|
+
coalesced: 0
|
|
149
242
|
};
|
|
150
243
|
}
|
|
151
244
|
/**
|
|
@@ -162,6 +255,7 @@ var MetadataCache = class {
|
|
|
162
255
|
hits: this.stats.hits,
|
|
163
256
|
misses: this.stats.misses,
|
|
164
257
|
evictions: this.stats.evictions,
|
|
258
|
+
coalesced: this.stats.coalesced,
|
|
165
259
|
hitRate
|
|
166
260
|
};
|
|
167
261
|
}
|
|
@@ -213,9 +307,9 @@ var ObjectStackError = class extends Error {
|
|
|
213
307
|
*/
|
|
214
308
|
constructor(message, code, statusCode, details) {
|
|
215
309
|
super(message);
|
|
216
|
-
this
|
|
217
|
-
this
|
|
218
|
-
this
|
|
310
|
+
__publicField(this, "code", code);
|
|
311
|
+
__publicField(this, "statusCode", statusCode);
|
|
312
|
+
__publicField(this, "details", details);
|
|
219
313
|
this.name = "ObjectStackError";
|
|
220
314
|
if (Error.captureStackTrace) {
|
|
221
315
|
Error.captureStackTrace(this, this.constructor);
|
|
@@ -269,9 +363,9 @@ var BulkOperationError = class extends ObjectStackError {
|
|
|
269
363
|
...details
|
|
270
364
|
}
|
|
271
365
|
);
|
|
272
|
-
this
|
|
273
|
-
this
|
|
274
|
-
this
|
|
366
|
+
__publicField(this, "successCount", successCount);
|
|
367
|
+
__publicField(this, "failureCount", failureCount);
|
|
368
|
+
__publicField(this, "errors", errors);
|
|
275
369
|
this.name = "BulkOperationError";
|
|
276
370
|
}
|
|
277
371
|
/**
|
|
@@ -298,7 +392,7 @@ var ConnectionError = class extends ObjectStackError {
|
|
|
298
392
|
statusCode || 503,
|
|
299
393
|
{ url, ...details }
|
|
300
394
|
);
|
|
301
|
-
this
|
|
395
|
+
__publicField(this, "url", url);
|
|
302
396
|
this.name = "ConnectionError";
|
|
303
397
|
}
|
|
304
398
|
};
|
|
@@ -333,8 +427,8 @@ var ValidationError = class extends ObjectStackError {
|
|
|
333
427
|
...details
|
|
334
428
|
}
|
|
335
429
|
);
|
|
336
|
-
this
|
|
337
|
-
this
|
|
430
|
+
__publicField(this, "field", field);
|
|
431
|
+
__publicField(this, "validationErrors", validationErrors);
|
|
338
432
|
this.name = "ValidationError";
|
|
339
433
|
}
|
|
340
434
|
/**
|
|
@@ -391,7 +485,7 @@ function isErrorType(error, errorClass) {
|
|
|
391
485
|
// src/cloud.ts
|
|
392
486
|
var CloudOperations = class {
|
|
393
487
|
constructor(getClient) {
|
|
394
|
-
this
|
|
488
|
+
__publicField(this, "getClient", getClient);
|
|
395
489
|
}
|
|
396
490
|
/**
|
|
397
491
|
* Deploy an application to the cloud.
|
|
@@ -735,10 +829,26 @@ function calculateAutoLayout(items, canvasWidth, padding = 40, gap = 40) {
|
|
|
735
829
|
}
|
|
736
830
|
|
|
737
831
|
// src/index.ts
|
|
832
|
+
var discoveryCache = /* @__PURE__ */ new Map();
|
|
833
|
+
async function getSharedDiscovery(baseUrl, fetcher) {
|
|
834
|
+
const key = baseUrl || "<default>";
|
|
835
|
+
const cached = discoveryCache.get(key);
|
|
836
|
+
if (cached) return cached;
|
|
837
|
+
const p = fetcher().catch((err) => {
|
|
838
|
+
discoveryCache.delete(key);
|
|
839
|
+
throw err;
|
|
840
|
+
});
|
|
841
|
+
discoveryCache.set(key, p);
|
|
842
|
+
return p;
|
|
843
|
+
}
|
|
844
|
+
function clearSharedDiscoveryCache() {
|
|
845
|
+
discoveryCache.clear();
|
|
846
|
+
}
|
|
738
847
|
var ObjectStackAdapter = class {
|
|
739
848
|
constructor(config) {
|
|
740
849
|
__publicField(this, "client");
|
|
741
850
|
__publicField(this, "connected", false);
|
|
851
|
+
__publicField(this, "connectPromise", null);
|
|
742
852
|
__publicField(this, "metadataCache");
|
|
743
853
|
__publicField(this, "connectionState", "disconnected");
|
|
744
854
|
__publicField(this, "connectionStateListeners", []);
|
|
@@ -764,10 +874,25 @@ var ObjectStackAdapter = class {
|
|
|
764
874
|
* Call this before making requests or it will auto-connect on first request.
|
|
765
875
|
*/
|
|
766
876
|
async connect() {
|
|
767
|
-
if (
|
|
768
|
-
|
|
877
|
+
if (this.connected) return;
|
|
878
|
+
if (this.connectPromise) return this.connectPromise;
|
|
879
|
+
this.setConnectionState("connecting");
|
|
880
|
+
this.connectPromise = (async () => {
|
|
769
881
|
try {
|
|
770
|
-
|
|
882
|
+
const baseUrl = this.baseUrl || "";
|
|
883
|
+
const discoveryUrl = baseUrl ? `${baseUrl.replace(/\/$/, "")}/api/v1/discovery` : "/api/v1/discovery";
|
|
884
|
+
const data = await getSharedDiscovery(baseUrl, async () => {
|
|
885
|
+
const res = await this.fetchImpl(discoveryUrl, {
|
|
886
|
+
method: "GET",
|
|
887
|
+
headers: this.token ? { Authorization: `Bearer ${this.token}` } : void 0
|
|
888
|
+
});
|
|
889
|
+
if (!res.ok) {
|
|
890
|
+
throw new Error(`discovery ${res.status} ${res.statusText}`);
|
|
891
|
+
}
|
|
892
|
+
const body = await res.json();
|
|
893
|
+
return body && typeof body.success === "boolean" && "data" in body ? body.data : body;
|
|
894
|
+
});
|
|
895
|
+
this.client.discoveryInfo = data;
|
|
771
896
|
this.connected = true;
|
|
772
897
|
this.reconnectAttempts = 0;
|
|
773
898
|
this.setConnectionState("connected");
|
|
@@ -784,8 +909,11 @@ var ObjectStackAdapter = class {
|
|
|
784
909
|
} else {
|
|
785
910
|
throw connectionError;
|
|
786
911
|
}
|
|
912
|
+
} finally {
|
|
913
|
+
this.connectPromise = null;
|
|
787
914
|
}
|
|
788
|
-
}
|
|
915
|
+
})();
|
|
916
|
+
return this.connectPromise;
|
|
789
917
|
}
|
|
790
918
|
/**
|
|
791
919
|
* Attempt to reconnect to the server with exponential backoff
|
|
@@ -1126,8 +1254,11 @@ var ObjectStackAdapter = class {
|
|
|
1126
1254
|
queryParams.set("sort", sortStr);
|
|
1127
1255
|
}
|
|
1128
1256
|
}
|
|
1129
|
-
if (params.$filter) {
|
|
1130
|
-
|
|
1257
|
+
if (params.$filter !== void 0 && params.$filter !== null) {
|
|
1258
|
+
const isEmpty = Array.isArray(params.$filter) ? params.$filter.length === 0 : typeof params.$filter === "object" && Object.keys(params.$filter).length === 0;
|
|
1259
|
+
if (!isEmpty) {
|
|
1260
|
+
queryParams.set("filter", JSON.stringify(params.$filter));
|
|
1261
|
+
}
|
|
1131
1262
|
}
|
|
1132
1263
|
const baseUrl = this.baseUrl.replace(/\/$/, "");
|
|
1133
1264
|
const qs = queryParams.toString();
|
|
@@ -1163,11 +1294,14 @@ var ObjectStackAdapter = class {
|
|
|
1163
1294
|
if (params.$select) {
|
|
1164
1295
|
options.select = params.$select;
|
|
1165
1296
|
}
|
|
1166
|
-
if (params.$filter) {
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1297
|
+
if (params.$filter !== void 0 && params.$filter !== null) {
|
|
1298
|
+
const isEmpty = Array.isArray(params.$filter) ? params.$filter.length === 0 : typeof params.$filter === "object" && Object.keys(params.$filter).length === 0;
|
|
1299
|
+
if (!isEmpty) {
|
|
1300
|
+
if (Array.isArray(params.$filter)) {
|
|
1301
|
+
options.filters = params.$filter;
|
|
1302
|
+
} else {
|
|
1303
|
+
options.filters = convertFiltersToAST(params.$filter);
|
|
1304
|
+
}
|
|
1171
1305
|
}
|
|
1172
1306
|
}
|
|
1173
1307
|
if (params.$orderby) {
|
|
@@ -1318,19 +1452,26 @@ var ObjectStackAdapter = class {
|
|
|
1318
1452
|
async aggregate(resource, params) {
|
|
1319
1453
|
await this.connect();
|
|
1320
1454
|
try {
|
|
1455
|
+
const measureName = params.function === "count" ? "count" : `${params.field}_${params.function}`;
|
|
1321
1456
|
const payload = {
|
|
1322
|
-
|
|
1323
|
-
measures: [
|
|
1324
|
-
dimensions
|
|
1457
|
+
cube: resource,
|
|
1458
|
+
measures: [measureName],
|
|
1459
|
+
// When groupBy is '_all' no dimensions are needed (single-bucket).
|
|
1460
|
+
dimensions: params.groupBy && params.groupBy !== "_all" ? [params.groupBy] : []
|
|
1325
1461
|
};
|
|
1326
1462
|
if (params.filter) {
|
|
1327
1463
|
payload.filters = params.filter;
|
|
1328
1464
|
}
|
|
1329
1465
|
const data = await this.client.analytics.query(payload);
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1466
|
+
const rawRows = Array.isArray(data) ? data : data?.rows && Array.isArray(data.rows) ? data.rows : data?.data && Array.isArray(data.data) ? data.data : data?.data?.rows && Array.isArray(data.data.rows) ? data.data.rows : data?.results && Array.isArray(data.results) ? data.results : [];
|
|
1467
|
+
return rawRows.map((row) => {
|
|
1468
|
+
const mapped = { ...row };
|
|
1469
|
+
if (measureName !== params.field && measureName in mapped) {
|
|
1470
|
+
mapped[params.field] = mapped[measureName];
|
|
1471
|
+
delete mapped[measureName];
|
|
1472
|
+
}
|
|
1473
|
+
return mapped;
|
|
1474
|
+
});
|
|
1334
1475
|
} catch {
|
|
1335
1476
|
const result = await this.find(resource);
|
|
1336
1477
|
const records = result.data || [];
|
|
@@ -1525,10 +1666,12 @@ function createObjectStackAdapter(config) {
|
|
|
1525
1666
|
SecurityManager,
|
|
1526
1667
|
ValidationError,
|
|
1527
1668
|
calculateAutoLayout,
|
|
1669
|
+
clearSharedDiscoveryCache,
|
|
1528
1670
|
createDefaultCanvasConfig,
|
|
1529
1671
|
createErrorFromResponse,
|
|
1530
1672
|
createObjectStackAdapter,
|
|
1531
1673
|
generateContractManifest,
|
|
1674
|
+
getSharedDiscovery,
|
|
1532
1675
|
isErrorType,
|
|
1533
1676
|
isObjectStackError,
|
|
1534
1677
|
snapToGrid,
|
package/dist/index.d.cts
CHANGED
|
@@ -156,6 +156,8 @@ interface CacheStats {
|
|
|
156
156
|
hits: number;
|
|
157
157
|
misses: number;
|
|
158
158
|
evictions: number;
|
|
159
|
+
/** Number of concurrent fetches that were coalesced onto an in-flight request. */
|
|
160
|
+
coalesced: number;
|
|
159
161
|
hitRate: number;
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -638,6 +640,14 @@ declare function calculateAutoLayout(items: Array<{
|
|
|
638
640
|
y: number;
|
|
639
641
|
}>;
|
|
640
642
|
|
|
643
|
+
/**
|
|
644
|
+
* Fetch the server `discovery` document once per (baseUrl) and reuse the
|
|
645
|
+
* resulting Promise. Used by `ObjectStackAdapter.connect()` (and any caller
|
|
646
|
+
* that wants the discovery payload without spinning up a new client).
|
|
647
|
+
*/
|
|
648
|
+
declare function getSharedDiscovery(baseUrl: string, fetcher: () => Promise<unknown>): Promise<unknown>;
|
|
649
|
+
/** Test/dev helper to drop the cache (e.g. on logout or origin change). */
|
|
650
|
+
declare function clearSharedDiscoveryCache(): void;
|
|
641
651
|
/**
|
|
642
652
|
* Connection state for monitoring
|
|
643
653
|
*/
|
|
@@ -701,6 +711,7 @@ type BatchProgressListener = (event: BatchProgressEvent) => void;
|
|
|
701
711
|
declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
702
712
|
private client;
|
|
703
713
|
private connected;
|
|
714
|
+
private connectPromise;
|
|
704
715
|
private metadataCache;
|
|
705
716
|
private connectionState;
|
|
706
717
|
private connectionStateListeners;
|
|
@@ -954,4 +965,4 @@ declare function createObjectStackAdapter<T = unknown>(config: {
|
|
|
954
965
|
reconnectDelay?: number;
|
|
955
966
|
}): DataSource<T>;
|
|
956
967
|
|
|
957
|
-
export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, MetadataNotFoundError, ObjectStackAdapter, ObjectStackError, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, generateContractManifest, isErrorType, isObjectStackError, snapToGrid, validatePluginContract };
|
|
968
|
+
export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, MetadataNotFoundError, ObjectStackAdapter, ObjectStackError, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, generateContractManifest, getSharedDiscovery, isErrorType, isObjectStackError, snapToGrid, validatePluginContract };
|
package/dist/index.d.ts
CHANGED
|
@@ -156,6 +156,8 @@ interface CacheStats {
|
|
|
156
156
|
hits: number;
|
|
157
157
|
misses: number;
|
|
158
158
|
evictions: number;
|
|
159
|
+
/** Number of concurrent fetches that were coalesced onto an in-flight request. */
|
|
160
|
+
coalesced: number;
|
|
159
161
|
hitRate: number;
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -638,6 +640,14 @@ declare function calculateAutoLayout(items: Array<{
|
|
|
638
640
|
y: number;
|
|
639
641
|
}>;
|
|
640
642
|
|
|
643
|
+
/**
|
|
644
|
+
* Fetch the server `discovery` document once per (baseUrl) and reuse the
|
|
645
|
+
* resulting Promise. Used by `ObjectStackAdapter.connect()` (and any caller
|
|
646
|
+
* that wants the discovery payload without spinning up a new client).
|
|
647
|
+
*/
|
|
648
|
+
declare function getSharedDiscovery(baseUrl: string, fetcher: () => Promise<unknown>): Promise<unknown>;
|
|
649
|
+
/** Test/dev helper to drop the cache (e.g. on logout or origin change). */
|
|
650
|
+
declare function clearSharedDiscoveryCache(): void;
|
|
641
651
|
/**
|
|
642
652
|
* Connection state for monitoring
|
|
643
653
|
*/
|
|
@@ -701,6 +711,7 @@ type BatchProgressListener = (event: BatchProgressEvent) => void;
|
|
|
701
711
|
declare class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
702
712
|
private client;
|
|
703
713
|
private connected;
|
|
714
|
+
private connectPromise;
|
|
704
715
|
private metadataCache;
|
|
705
716
|
private connectionState;
|
|
706
717
|
private connectionStateListeners;
|
|
@@ -954,4 +965,4 @@ declare function createObjectStackAdapter<T = unknown>(config: {
|
|
|
954
965
|
reconnectDelay?: number;
|
|
955
966
|
}): DataSource<T>;
|
|
956
967
|
|
|
957
|
-
export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, MetadataNotFoundError, ObjectStackAdapter, ObjectStackError, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, generateContractManifest, isErrorType, isObjectStackError, snapToGrid, validatePluginContract };
|
|
968
|
+
export { type AuditEventType, type AuditLogConfig, type AuditLogEntry, AuthenticationError, type BatchProgressEvent, type BatchProgressListener, BulkOperationError, type CSPConfig, type CacheStats, type CloudDeploymentConfig, type CloudHostingConfig, type CloudMarketplaceEntry, CloudOperations, ConnectionError, type ConnectionState, type ConnectionStateEvent, type ConnectionStateListener, type ContractValidationError, type ContractValidationResult, type DataMaskingConfig, type DataMaskingRule, type EmailIntegrationConfig, type IntegrationConfig, IntegrationManager, type IntegrationProvider, type IntegrationTrigger, MetadataNotFoundError, ObjectStackAdapter, ObjectStackError, type PluginAPIContract, type PluginContract, type PluginExport, SecurityManager, type SecurityPolicy, type SlackIntegrationConfig, type StudioCanvasConfig, type StudioColorPalette, type StudioPropertyEditor, type StudioShadowPreset, type StudioThemeBuilderConfig, type StudioTypographyPreset, ValidationError, type WebhookIntegrationConfig, calculateAutoLayout, clearSharedDiscoveryCache, createDefaultCanvasConfig, createErrorFromResponse, createObjectStackAdapter, generateContractManifest, getSharedDiscovery, isErrorType, isObjectStackError, snapToGrid, validatePluginContract };
|