@anchrd/intel-api 0.6.6 → 0.6.7
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/adapters/db/db-flows.js +13 -0
- package/dist/adapters/db/db.js +18 -2
- package/dist/http/http.js +5 -2
- package/package.json +1 -1
|
@@ -128,6 +128,19 @@ export function createFlowRepository(deps) {
|
|
|
128
128
|
ORDER BY lower(flow.title), flow.id${bounded ? " LIMIT ?" : ""}`;
|
|
129
129
|
return {
|
|
130
130
|
async listVisible(actor, input = {}) {
|
|
131
|
+
// ⚠️ `archivedOnly` overrides the folder rather than narrowing within it: somebody looking
|
|
132
|
+
// for what they archived does not know where it was filed (#113). The visibility predicate
|
|
133
|
+
// is unchanged, so the archive shows no flow the tree would have hidden.
|
|
134
|
+
if (input.archivedOnly === true) {
|
|
135
|
+
const result = await deps.db
|
|
136
|
+
.prepare(`${subtreeCte}
|
|
137
|
+
SELECT ${flowColumns} FROM flows flow
|
|
138
|
+
WHERE ${flowInSubtree} AND flow.archived_at IS NOT NULL
|
|
139
|
+
ORDER BY flow.archived_at DESC, lower(flow.title), flow.id`)
|
|
140
|
+
.bind(...readableBindings(actor), ...flowInSubtreeBindings(actor))
|
|
141
|
+
.all();
|
|
142
|
+
return (result.results ?? []).map(mapFlow);
|
|
143
|
+
}
|
|
131
144
|
const scope = scopeOf(input.parentId);
|
|
132
145
|
const result = await deps.db
|
|
133
146
|
.prepare(visibleFlows(scope.clause, false, input.includeArchived === true))
|
package/dist/adapters/db/db.js
CHANGED
|
@@ -102,11 +102,27 @@ export function createKnowledgeRepository(deps) {
|
|
|
102
102
|
JOIN allowed ON allowed.id = n.id
|
|
103
103
|
WHERE n.parent_id IS ? AND (? = 1 OR n.archived_at IS NULL)
|
|
104
104
|
ORDER BY CASE n.kind WHEN 'folder' THEN 0 ELSE 1 END, lower(n.title), n.id${bounded ? " LIMIT ?" : ""}`;
|
|
105
|
+
/**
|
|
106
|
+
* Everything archived that this actor may see, wherever it sits (#113).
|
|
107
|
+
*
|
|
108
|
+
* ⚠️ No `parent_id` at all, and that is the point rather than an omission: somebody looking for
|
|
109
|
+
* what they archived does not know which folder it was in. The visibility predicate is the same
|
|
110
|
+
* `allowed` set every other read uses, so the archive shows no more than the tree would have.
|
|
111
|
+
*
|
|
112
|
+
* `has_children` is answered as 0 without asking: an archived row is not expandable — its
|
|
113
|
+
* children are reached by restoring it, not by opening it here.
|
|
114
|
+
*/
|
|
115
|
+
const archivedEverywhere = `${visibleCte}
|
|
116
|
+
SELECT ${nodeColumns}, 0 AS has_children
|
|
117
|
+
FROM knowledge_nodes n
|
|
118
|
+
JOIN allowed ON allowed.id = n.id
|
|
119
|
+
WHERE n.archived_at IS NOT NULL
|
|
120
|
+
ORDER BY n.archived_at DESC, lower(n.title), n.id`;
|
|
105
121
|
return {
|
|
106
122
|
async listVisible(actor, input) {
|
|
107
123
|
const result = await deps.db
|
|
108
|
-
.prepare(visibleChildren(false))
|
|
109
|
-
.bind(...readBindings(actor), input.parentId, input.includeArchived ? 1 : 0)
|
|
124
|
+
.prepare(input.archivedOnly ? archivedEverywhere : visibleChildren(false))
|
|
125
|
+
.bind(...readBindings(actor), ...(input.archivedOnly ? [] : [input.parentId, input.includeArchived ? 1 : 0]))
|
|
110
126
|
.all();
|
|
111
127
|
const rows = result.results ?? [];
|
|
112
128
|
return {
|
package/dist/http/http.js
CHANGED
|
@@ -101,8 +101,9 @@ export function createHttp(deps) {
|
|
|
101
101
|
const url = new URL(context.req.url);
|
|
102
102
|
const unknownQuery = [];
|
|
103
103
|
url.searchParams.forEach((_value, key) => {
|
|
104
|
-
if (key !== "parentId" && key !== "includeArchived")
|
|
104
|
+
if (key !== "parentId" && key !== "includeArchived" && key !== "archivedOnly") {
|
|
105
105
|
unknownQuery.push(key);
|
|
106
|
+
}
|
|
106
107
|
});
|
|
107
108
|
if (unknownQuery.length) {
|
|
108
109
|
throw new IntelError(400, "invalid_request", `Unknown query parameters: ${unknownQuery.join(", ")}`);
|
|
@@ -110,6 +111,7 @@ export function createHttp(deps) {
|
|
|
110
111
|
const input = ListKnowledgeNodesInput.parse({
|
|
111
112
|
parentId: url.searchParams.get("parentId"),
|
|
112
113
|
includeArchived: url.searchParams.get("includeArchived") === "true",
|
|
114
|
+
...(url.searchParams.get("archivedOnly") === "true" ? { archivedOnly: true } : {}),
|
|
113
115
|
});
|
|
114
116
|
return context.json(await deps.knowledge.list(asActor(auth), input));
|
|
115
117
|
});
|
|
@@ -250,7 +252,7 @@ export function createHttp(deps) {
|
|
|
250
252
|
app.get("/flows", async (context) => {
|
|
251
253
|
const auth = requireCapability(context, "flows", "read");
|
|
252
254
|
const url = new URL(context.req.url);
|
|
253
|
-
requireKnownQuery(url, ["parentId", "includeArchived"]);
|
|
255
|
+
requireKnownQuery(url, ["parentId", "includeArchived", "archivedOnly"]);
|
|
254
256
|
// Absent means "every flow I may see"; present but empty means the root of the shared tree.
|
|
255
257
|
// Without that distinction a tree level and a full list would be the same request.
|
|
256
258
|
const parentId = url.searchParams.get("parentId");
|
|
@@ -259,6 +261,7 @@ export function createHttp(deps) {
|
|
|
259
261
|
const input = ListFlowsInput.parse({
|
|
260
262
|
...(url.searchParams.has("parentId") ? { parentId: parentId === "" ? null : parentId } : {}),
|
|
261
263
|
...(url.searchParams.get("includeArchived") === "true" ? { includeArchived: true } : {}),
|
|
264
|
+
...(url.searchParams.get("archivedOnly") === "true" ? { archivedOnly: true } : {}),
|
|
262
265
|
});
|
|
263
266
|
return context.json(await deps.flows.list(asFlowActor(auth), input));
|
|
264
267
|
});
|