@objectstack/rest 9.2.0 → 9.4.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/dist/index.cjs +96 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +96 -5
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -871,6 +871,9 @@ var RestServer = class {
|
|
|
871
871
|
*/
|
|
872
872
|
filterAppForUser(item, sysPerms) {
|
|
873
873
|
if (!item || typeof item !== "object") return item;
|
|
874
|
+
if (item.hidden === true && !sysPerms.has("studio.access") && !sysPerms.has("setup.access")) {
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
874
877
|
const reqApp = Array.isArray(item.requiredPermissions) ? item.requiredPermissions : [];
|
|
875
878
|
if (reqApp.length > 0 && !reqApp.every((p) => sysPerms.has(p))) {
|
|
876
879
|
return null;
|
|
@@ -1488,9 +1491,11 @@ var RestServer = class {
|
|
|
1488
1491
|
const packageId = req.query?.package || void 0;
|
|
1489
1492
|
const environmentId = isScoped ? req.params?.environmentId : void 0;
|
|
1490
1493
|
const p = await this.resolveProtocol(environmentId, req);
|
|
1494
|
+
const previewDrafts = typeof req.query?.preview === "string" && req.query.preview.toLowerCase() === "draft";
|
|
1491
1495
|
const items = await p.getMetaItems({
|
|
1492
1496
|
type: req.params.type,
|
|
1493
1497
|
packageId,
|
|
1498
|
+
...previewDrafts ? { previewDrafts: true } : {},
|
|
1494
1499
|
...environmentId ? { environmentId } : {}
|
|
1495
1500
|
});
|
|
1496
1501
|
let visible = items;
|
|
@@ -1517,6 +1522,18 @@ var RestServer = class {
|
|
|
1517
1522
|
visible = Array.isArray(raw) ? filtered : { ...raw, items: filtered };
|
|
1518
1523
|
}
|
|
1519
1524
|
}
|
|
1525
|
+
if (req.params.type === "doc" && req.query?.include !== "content") {
|
|
1526
|
+
const raw = visible;
|
|
1527
|
+
const list = Array.isArray(raw) ? raw : raw && typeof raw === "object" && Array.isArray(raw.items) ? raw.items : null;
|
|
1528
|
+
if (list) {
|
|
1529
|
+
const slim = list.map((it) => {
|
|
1530
|
+
if (!it || typeof it !== "object") return it;
|
|
1531
|
+
const { content: _content, ...rest } = it;
|
|
1532
|
+
return rest;
|
|
1533
|
+
});
|
|
1534
|
+
visible = Array.isArray(raw) ? slim : { ...raw, items: slim };
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1520
1537
|
const translated = await this.translateMetaItems(req, req.params.type, environmentId, visible);
|
|
1521
1538
|
res.header("Vary", "Accept-Language");
|
|
1522
1539
|
res.json(translated);
|
|
@@ -1568,9 +1585,11 @@ var RestServer = class {
|
|
|
1568
1585
|
const p = await this.resolveProtocol(environmentId, req);
|
|
1569
1586
|
const wantLayered = req.query?.layers !== void 0 && req.query?.layers !== "";
|
|
1570
1587
|
if (wantLayered && typeof p.getMetaItemLayered === "function") {
|
|
1588
|
+
const layeredPackageId = req.query?.package || void 0;
|
|
1571
1589
|
const layered = await p.getMetaItemLayered({
|
|
1572
1590
|
type: req.params.type,
|
|
1573
1591
|
name: req.params.name,
|
|
1592
|
+
...layeredPackageId ? { packageId: layeredPackageId } : {},
|
|
1574
1593
|
...environmentId ? { environmentId } : {}
|
|
1575
1594
|
});
|
|
1576
1595
|
res.json(layered);
|
|
@@ -1578,7 +1597,9 @@ var RestServer = class {
|
|
|
1578
1597
|
}
|
|
1579
1598
|
const isAppType = req.params.type === "app";
|
|
1580
1599
|
const isDraftRead = typeof req.query?.state === "string" && req.query.state.toLowerCase() === "draft";
|
|
1581
|
-
|
|
1600
|
+
const previewDrafts = typeof req.query?.preview === "string" && req.query.preview.toLowerCase() === "draft";
|
|
1601
|
+
const packageScoped = typeof req.query?.package === "string" && req.query.package.length > 0;
|
|
1602
|
+
if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts && !packageScoped) {
|
|
1582
1603
|
const cacheRequest = {
|
|
1583
1604
|
ifNoneMatch: req.headers["if-none-match"],
|
|
1584
1605
|
ifModifiedSince: req.headers["if-modified-since"]
|
|
@@ -1617,7 +1638,8 @@ var RestServer = class {
|
|
|
1617
1638
|
type: req.params.type,
|
|
1618
1639
|
name: req.params.name,
|
|
1619
1640
|
packageId,
|
|
1620
|
-
...stateParam === "draft" ? { state: "draft" } : {}
|
|
1641
|
+
...stateParam === "draft" ? { state: "draft" } : {},
|
|
1642
|
+
...previewDrafts ? { previewDrafts: true } : {}
|
|
1621
1643
|
});
|
|
1622
1644
|
let visible = item;
|
|
1623
1645
|
if (isAppType && item) {
|
|
@@ -3582,6 +3604,7 @@ var RestServer = class {
|
|
|
3582
3604
|
[/^VALIDATION_FAILED/, 400, "VALIDATION_FAILED"],
|
|
3583
3605
|
[/^DUPLICATE_REQUEST/, 409, "DUPLICATE_REQUEST"],
|
|
3584
3606
|
[/^INVALID_STATE/, 409, "INVALID_STATE"],
|
|
3607
|
+
[/^THROTTLED/, 429, "THROTTLED"],
|
|
3585
3608
|
[/^FORBIDDEN/, 403, "FORBIDDEN"],
|
|
3586
3609
|
[/^REQUEST_NOT_FOUND/, 404, "REQUEST_NOT_FOUND"]
|
|
3587
3610
|
];
|
|
@@ -3609,13 +3632,24 @@ var RestServer = class {
|
|
|
3609
3632
|
const q = req.query ?? {};
|
|
3610
3633
|
const rawApprover = q.approverId ?? q.approver_id;
|
|
3611
3634
|
const approverIds = (Array.isArray(rawApprover) ? rawApprover : rawApprover != null ? [rawApprover] : []).flatMap((s) => String(s).split(",")).map((s) => s.trim()).filter(Boolean);
|
|
3612
|
-
const
|
|
3635
|
+
const limit = q.limit != null ? Number(q.limit) : void 0;
|
|
3636
|
+
const offset = q.offset != null ? Number(q.offset) : void 0;
|
|
3637
|
+
const listFilter = {
|
|
3613
3638
|
object: q.object,
|
|
3614
3639
|
recordId: q.recordId ?? q.record_id,
|
|
3615
3640
|
status: q.status,
|
|
3616
3641
|
approverId: approverIds.length ? approverIds : void 0,
|
|
3617
|
-
submitterId: q.submitterId ?? q.submitter_id
|
|
3618
|
-
|
|
3642
|
+
submitterId: q.submitterId ?? q.submitter_id,
|
|
3643
|
+
q: typeof q.q === "string" ? q.q : void 0,
|
|
3644
|
+
limit: Number.isFinite(limit) ? limit : void 0,
|
|
3645
|
+
offset: Number.isFinite(offset) ? offset : void 0
|
|
3646
|
+
};
|
|
3647
|
+
const rows = await svc.listRequests(listFilter, context ?? {});
|
|
3648
|
+
if (listFilter.limit != null && typeof svc.countRequests === "function") {
|
|
3649
|
+
const total = await svc.countRequests(listFilter, context ?? {});
|
|
3650
|
+
res.json({ data: rows, total });
|
|
3651
|
+
return;
|
|
3652
|
+
}
|
|
3619
3653
|
res.json({ data: rows });
|
|
3620
3654
|
} catch (error) {
|
|
3621
3655
|
logError("[REST] List approval requests error:", error);
|
|
@@ -3708,6 +3742,63 @@ var RestServer = class {
|
|
|
3708
3742
|
},
|
|
3709
3743
|
metadata: { summary: "Recall (withdraw) an approval request", tags: ["approvals"] }
|
|
3710
3744
|
});
|
|
3745
|
+
const threadRoute = (action, invoke) => {
|
|
3746
|
+
this.routeManager.register({
|
|
3747
|
+
method: "POST",
|
|
3748
|
+
path: `${dataPath}/approvals/requests/:id/${action}`,
|
|
3749
|
+
handler: async (req, res) => {
|
|
3750
|
+
try {
|
|
3751
|
+
const environmentId = isScoped ? req.params?.environmentId : void 0;
|
|
3752
|
+
const context = await this.resolveExecCtx(environmentId, req);
|
|
3753
|
+
if (this.enforceAuth(req, res, context)) return;
|
|
3754
|
+
const svc = await resolveService(environmentId);
|
|
3755
|
+
if (!svc) return respond501(res);
|
|
3756
|
+
const body = req.body ?? {};
|
|
3757
|
+
try {
|
|
3758
|
+
const out = await invoke(svc, req.params.id, body, context ?? {});
|
|
3759
|
+
res.json(out);
|
|
3760
|
+
} catch (err) {
|
|
3761
|
+
if (handleApprovalError(res, err)) return;
|
|
3762
|
+
throw err;
|
|
3763
|
+
}
|
|
3764
|
+
} catch (error) {
|
|
3765
|
+
logError(`[REST] ${action} approval error:`, error);
|
|
3766
|
+
res.status(500).json({ code: `APPROVAL_${action.toUpperCase().replace("-", "_")}_FAILED`, error: String(error?.message ?? error).slice(0, 500) });
|
|
3767
|
+
}
|
|
3768
|
+
},
|
|
3769
|
+
metadata: { summary: `${action} on an approval request`, tags: ["approvals"] }
|
|
3770
|
+
});
|
|
3771
|
+
};
|
|
3772
|
+
threadRoute("reassign", (svc, id, body, context) => {
|
|
3773
|
+
if (typeof svc.reassign !== "function") throw new Error("VALIDATION_FAILED: reassign is not supported");
|
|
3774
|
+
return svc.reassign(id, {
|
|
3775
|
+
actorId: body.actorId ?? body.actor_id ?? context?.userId,
|
|
3776
|
+
to: body.to,
|
|
3777
|
+
from: body.from,
|
|
3778
|
+
comment: body.comment
|
|
3779
|
+
}, context);
|
|
3780
|
+
});
|
|
3781
|
+
threadRoute("remind", (svc, id, body, context) => {
|
|
3782
|
+
if (typeof svc.remind !== "function") throw new Error("VALIDATION_FAILED: remind is not supported");
|
|
3783
|
+
return svc.remind(id, {
|
|
3784
|
+
actorId: body.actorId ?? body.actor_id ?? context?.userId,
|
|
3785
|
+
comment: body.comment
|
|
3786
|
+
}, context);
|
|
3787
|
+
});
|
|
3788
|
+
threadRoute("request-info", (svc, id, body, context) => {
|
|
3789
|
+
if (typeof svc.requestInfo !== "function") throw new Error("VALIDATION_FAILED: request-info is not supported");
|
|
3790
|
+
return svc.requestInfo(id, {
|
|
3791
|
+
actorId: body.actorId ?? body.actor_id ?? context?.userId,
|
|
3792
|
+
comment: body.comment
|
|
3793
|
+
}, context);
|
|
3794
|
+
});
|
|
3795
|
+
threadRoute("comment", (svc, id, body, context) => {
|
|
3796
|
+
if (typeof svc.comment !== "function") throw new Error("VALIDATION_FAILED: comment is not supported");
|
|
3797
|
+
return svc.comment(id, {
|
|
3798
|
+
actorId: body.actorId ?? body.actor_id ?? context?.userId,
|
|
3799
|
+
comment: body.comment
|
|
3800
|
+
}, context);
|
|
3801
|
+
});
|
|
3711
3802
|
this.routeManager.register({
|
|
3712
3803
|
method: "GET",
|
|
3713
3804
|
path: `${dataPath}/approvals/requests/:id/actions`,
|