@object-ui/data-objectstack 4.0.10 → 4.0.11
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 +7 -0
- package/dist/index.cjs +24 -5
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -5
- package/package.json +3 -3
- package/src/index.ts +30 -4
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -962,6 +962,11 @@ var ObjectStackAdapter = class {
|
|
|
962
962
|
// multiple sibling components requesting the same dataset on first paint)
|
|
963
963
|
// into a single network round trip.
|
|
964
964
|
__publicField(this, "inflightFinds", /* @__PURE__ */ new Map());
|
|
965
|
+
// Resources that have responded 404 at least once (collection not installed
|
|
966
|
+
// on this backend). Subsequent find() calls short-circuit to an empty result
|
|
967
|
+
// so optional collections like sys_presence don't hammer the server with
|
|
968
|
+
// failing requests on every record open / panel render.
|
|
969
|
+
__publicField(this, "missingResources", /* @__PURE__ */ new Set());
|
|
965
970
|
this.client = new import_client.ObjectStackClient({ ...config, logger: createQuietHttpLogger() });
|
|
966
971
|
this.metadataCache = new MetadataCache(config.cache);
|
|
967
972
|
this.autoReconnect = config.autoReconnect ?? true;
|
|
@@ -1099,18 +1104,29 @@ var ObjectStackAdapter = class {
|
|
|
1099
1104
|
* Converts OData-style params to ObjectStack query options.
|
|
1100
1105
|
*/
|
|
1101
1106
|
async find(resource, params) {
|
|
1107
|
+
if (this.missingResources.has(resource)) {
|
|
1108
|
+
return { data: [], total: 0 };
|
|
1109
|
+
}
|
|
1102
1110
|
const key = `${resource}::${stableStringify(params)}`;
|
|
1103
1111
|
const existing = this.inflightFinds.get(key);
|
|
1104
1112
|
if (existing) return existing;
|
|
1105
1113
|
const promise = (async () => {
|
|
1106
1114
|
await this.connect();
|
|
1107
1115
|
if (params?.$expand && params.$expand.length > 0) {
|
|
1108
|
-
const
|
|
1109
|
-
return this.normalizeQueryResult(
|
|
1116
|
+
const result = await this.rawFindWithPopulate(resource, params);
|
|
1117
|
+
return this.normalizeQueryResult(result, params);
|
|
1110
1118
|
}
|
|
1111
1119
|
const queryOptions = this.convertQueryParams(params);
|
|
1112
|
-
|
|
1113
|
-
|
|
1120
|
+
try {
|
|
1121
|
+
const result = await this.client.data.find(resource, queryOptions);
|
|
1122
|
+
return this.normalizeQueryResult(result, params);
|
|
1123
|
+
} catch (err) {
|
|
1124
|
+
if (is404Error(err)) {
|
|
1125
|
+
this.missingResources.add(resource);
|
|
1126
|
+
return { data: [], total: 0 };
|
|
1127
|
+
}
|
|
1128
|
+
throw err;
|
|
1129
|
+
}
|
|
1114
1130
|
})();
|
|
1115
1131
|
this.inflightFinds.set(key, promise);
|
|
1116
1132
|
const cleanup = () => {
|
|
@@ -1640,7 +1656,10 @@ var ObjectStackAdapter = class {
|
|
|
1640
1656
|
await this.connect();
|
|
1641
1657
|
let name = String(spec?.name || "").trim();
|
|
1642
1658
|
if (!name) {
|
|
1643
|
-
|
|
1659
|
+
let base = String(spec?.label || objectName || "view").toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 40);
|
|
1660
|
+
if (!base || /^[0-9]/.test(base)) {
|
|
1661
|
+
base = base ? `view_${base}` : "view";
|
|
1662
|
+
}
|
|
1644
1663
|
const suffix = Date.now().toString(36);
|
|
1645
1664
|
name = `${base}_${suffix}`;
|
|
1646
1665
|
}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -919,6 +919,11 @@ var ObjectStackAdapter = class {
|
|
|
919
919
|
// multiple sibling components requesting the same dataset on first paint)
|
|
920
920
|
// into a single network round trip.
|
|
921
921
|
__publicField(this, "inflightFinds", /* @__PURE__ */ new Map());
|
|
922
|
+
// Resources that have responded 404 at least once (collection not installed
|
|
923
|
+
// on this backend). Subsequent find() calls short-circuit to an empty result
|
|
924
|
+
// so optional collections like sys_presence don't hammer the server with
|
|
925
|
+
// failing requests on every record open / panel render.
|
|
926
|
+
__publicField(this, "missingResources", /* @__PURE__ */ new Set());
|
|
922
927
|
this.client = new ObjectStackClient({ ...config, logger: createQuietHttpLogger() });
|
|
923
928
|
this.metadataCache = new MetadataCache(config.cache);
|
|
924
929
|
this.autoReconnect = config.autoReconnect ?? true;
|
|
@@ -1056,18 +1061,29 @@ var ObjectStackAdapter = class {
|
|
|
1056
1061
|
* Converts OData-style params to ObjectStack query options.
|
|
1057
1062
|
*/
|
|
1058
1063
|
async find(resource, params) {
|
|
1064
|
+
if (this.missingResources.has(resource)) {
|
|
1065
|
+
return { data: [], total: 0 };
|
|
1066
|
+
}
|
|
1059
1067
|
const key = `${resource}::${stableStringify(params)}`;
|
|
1060
1068
|
const existing = this.inflightFinds.get(key);
|
|
1061
1069
|
if (existing) return existing;
|
|
1062
1070
|
const promise = (async () => {
|
|
1063
1071
|
await this.connect();
|
|
1064
1072
|
if (params?.$expand && params.$expand.length > 0) {
|
|
1065
|
-
const
|
|
1066
|
-
return this.normalizeQueryResult(
|
|
1073
|
+
const result = await this.rawFindWithPopulate(resource, params);
|
|
1074
|
+
return this.normalizeQueryResult(result, params);
|
|
1067
1075
|
}
|
|
1068
1076
|
const queryOptions = this.convertQueryParams(params);
|
|
1069
|
-
|
|
1070
|
-
|
|
1077
|
+
try {
|
|
1078
|
+
const result = await this.client.data.find(resource, queryOptions);
|
|
1079
|
+
return this.normalizeQueryResult(result, params);
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
if (is404Error(err)) {
|
|
1082
|
+
this.missingResources.add(resource);
|
|
1083
|
+
return { data: [], total: 0 };
|
|
1084
|
+
}
|
|
1085
|
+
throw err;
|
|
1086
|
+
}
|
|
1071
1087
|
})();
|
|
1072
1088
|
this.inflightFinds.set(key, promise);
|
|
1073
1089
|
const cleanup = () => {
|
|
@@ -1597,7 +1613,10 @@ var ObjectStackAdapter = class {
|
|
|
1597
1613
|
await this.connect();
|
|
1598
1614
|
let name = String(spec?.name || "").trim();
|
|
1599
1615
|
if (!name) {
|
|
1600
|
-
|
|
1616
|
+
let base = String(spec?.label || objectName || "view").toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 40);
|
|
1617
|
+
if (!base || /^[0-9]/.test(base)) {
|
|
1618
|
+
base = base ? `view_${base}` : "view";
|
|
1619
|
+
}
|
|
1601
1620
|
const suffix = Date.now().toString(36);
|
|
1602
1621
|
name = `${base}_${suffix}`;
|
|
1603
1622
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/data-objectstack",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.11",
|
|
4
4
|
"description": "ObjectStack Data Adapter for Object UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@objectstack/client": "^4.0.5",
|
|
26
|
-
"@object-ui/core": "4.0.
|
|
27
|
-
"@object-ui/types": "4.0.
|
|
26
|
+
"@object-ui/core": "4.0.11",
|
|
27
|
+
"@object-ui/types": "4.0.11"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"tsup": "^8.5.1",
|
package/src/index.ts
CHANGED
|
@@ -275,6 +275,11 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
|
275
275
|
// multiple sibling components requesting the same dataset on first paint)
|
|
276
276
|
// into a single network round trip.
|
|
277
277
|
private inflightFinds = new Map<string, Promise<QueryResult<T>>>();
|
|
278
|
+
// Resources that have responded 404 at least once (collection not installed
|
|
279
|
+
// on this backend). Subsequent find() calls short-circuit to an empty result
|
|
280
|
+
// so optional collections like sys_presence don't hammer the server with
|
|
281
|
+
// failing requests on every record open / panel render.
|
|
282
|
+
private missingResources = new Set<string>();
|
|
278
283
|
|
|
279
284
|
constructor(config: {
|
|
280
285
|
baseUrl: string;
|
|
@@ -470,6 +475,12 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
|
470
475
|
* Converts OData-style params to ObjectStack query options.
|
|
471
476
|
*/
|
|
472
477
|
async find(resource: string, params?: QueryParams): Promise<QueryResult<T>> {
|
|
478
|
+
// Short-circuit when this resource has previously responded 404 — the
|
|
479
|
+
// collection isn't installed on this backend. Callers (AppHeader,
|
|
480
|
+
// RecordDetailView, …) treat empty data as "feature unavailable".
|
|
481
|
+
if (this.missingResources.has(resource)) {
|
|
482
|
+
return { data: [], total: 0 } as QueryResult<T>;
|
|
483
|
+
}
|
|
473
484
|
const key = `${resource}::${stableStringify(params)}`;
|
|
474
485
|
const existing = this.inflightFinds.get(key);
|
|
475
486
|
if (existing) return existing;
|
|
@@ -489,8 +500,17 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
|
489
500
|
}
|
|
490
501
|
|
|
491
502
|
const queryOptions = this.convertQueryParams(params);
|
|
492
|
-
|
|
493
|
-
|
|
503
|
+
try {
|
|
504
|
+
const result: unknown = await this.client.data.find<T>(resource, queryOptions);
|
|
505
|
+
return this.normalizeQueryResult(result, params);
|
|
506
|
+
} catch (err) {
|
|
507
|
+
if (is404Error(err)) {
|
|
508
|
+
// Mark the resource so subsequent calls don't repeat the 404.
|
|
509
|
+
this.missingResources.add(resource);
|
|
510
|
+
return { data: [], total: 0 } as QueryResult<T>;
|
|
511
|
+
}
|
|
512
|
+
throw err;
|
|
513
|
+
}
|
|
494
514
|
})();
|
|
495
515
|
|
|
496
516
|
this.inflightFinds.set(key, promise);
|
|
@@ -1188,11 +1208,17 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
|
|
|
1188
1208
|
await this.connect();
|
|
1189
1209
|
let name = String(spec?.name || '').trim();
|
|
1190
1210
|
if (!name) {
|
|
1191
|
-
|
|
1211
|
+
let base = String(spec?.label || objectName || 'view')
|
|
1192
1212
|
.toLowerCase()
|
|
1193
1213
|
.replace(/[^a-z0-9_]+/g, '_')
|
|
1194
1214
|
.replace(/^_+|_+$/g, '')
|
|
1195
|
-
.slice(0, 40)
|
|
1215
|
+
.slice(0, 40);
|
|
1216
|
+
// Spec requires snake_case starting with a letter or underscore.
|
|
1217
|
+
// Labels like "表格 1" collapse to "1" after non-ascii stripping, so we
|
|
1218
|
+
// need a fallback / prefix to keep the identifier valid.
|
|
1219
|
+
if (!base || /^[0-9]/.test(base)) {
|
|
1220
|
+
base = base ? `view_${base}` : 'view';
|
|
1221
|
+
}
|
|
1196
1222
|
const suffix = Date.now().toString(36);
|
|
1197
1223
|
name = `${base}_${suffix}`;
|
|
1198
1224
|
}
|