mirror of
https://github.com/logseq/logseq.git
synced 2026-04-24 22:25:01 +00:00
impl 013-logseq-cli-datascript-query.md (1)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -77,5 +77,3 @@ clj-e2e/e2e-dump
|
||||
.dir-locals.el
|
||||
.projectile
|
||||
*.map
|
||||
/dist/db-worker-node.js
|
||||
/dist/logseq-cli.js
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
## db-worker-node
|
||||
- Build: `clojure -M:cljs compile db-worker-node`
|
||||
- Run: `node ./dist/db-worker-node.js` (default port 9101)
|
||||
- Run: `node ./static/db-worker-node.js` (default port 9101)
|
||||
|
||||
## Common used cljs keywords
|
||||
- All commonly used ClojureScript keywords are defined using `logseq.common.defkeywords/defkeyword`.
|
||||
|
||||
2
bb.edn
2
bb.edn
@@ -180,7 +180,7 @@
|
||||
{:doc "Compile and start db-worker-node (pass-through args forwarded to node)"
|
||||
:task (do
|
||||
(shell "clojure" "-M:cljs" "compile" "db-worker-node")
|
||||
(apply shell "node" "./dist/db-worker-node.js" *command-line-args*))}
|
||||
(apply shell "node" "./static/db-worker-node.js" *command-line-args*))}
|
||||
|
||||
lint:dev
|
||||
logseq.tasks.dev.lint/dev
|
||||
|
||||
2
deps.edn
2
deps.edn
@@ -5,7 +5,7 @@
|
||||
:sha "5d672bf84ed944414b9f61eeb83808ead7be9127"}
|
||||
|
||||
datascript/datascript {:git/url "https://github.com/logseq/datascript" ;; fork
|
||||
:sha "ff5a7d5326e2546f40146e4a489343f557519bc3"}
|
||||
:sha "d6305968aa05bd309abd6d764908cf04ea8000b9"}
|
||||
;; datascript/datascript {:local/root "../../datascript"}
|
||||
|
||||
datascript-transit/datascript-transit {:mvn/version "0.3.0"}
|
||||
|
||||
2
deps/db/deps.edn
vendored
2
deps/db/deps.edn
vendored
@@ -1,7 +1,7 @@
|
||||
{:deps
|
||||
;; These nbb-logseq deps are kept in sync with https://github.com/logseq/nbb-logseq/blob/main/bb.edn
|
||||
{datascript/datascript {:git/url "https://github.com/logseq/datascript" ;; fork
|
||||
:sha "ff5a7d5326e2546f40146e4a489343f557519bc3"}
|
||||
:sha "d6305968aa05bd309abd6d764908cf04ea8000b9"}
|
||||
;; datascript/datascript {:local/root "../../../../datascript"}
|
||||
datascript-transit/datascript-transit {:mvn/version "0.3.0"
|
||||
:exclusions [datascript/datascript]}
|
||||
|
||||
2
deps/outliner/deps.edn
vendored
2
deps/outliner/deps.edn
vendored
@@ -1,7 +1,7 @@
|
||||
{:deps
|
||||
;; These nbb-logseq deps are kept in sync with https://github.com/logseq/nbb-logseq/blob/main/bb.edn
|
||||
{datascript/datascript {:git/url "https://github.com/logseq/datascript" ;; fork
|
||||
:sha "ff5a7d5326e2546f40146e4a489343f557519bc3"}
|
||||
:sha "d6305968aa05bd309abd6d764908cf04ea8000b9"}
|
||||
;; datascript/datascript {:local/root "../../../../datascript"}
|
||||
com.cognitect/transit-cljs {:mvn/version "0.8.280"}
|
||||
|
||||
|
||||
2
deps/publish/deps.edn
vendored
2
deps/publish/deps.edn
vendored
@@ -5,7 +5,7 @@
|
||||
:sha "5d672bf84ed944414b9f61eeb83808ead7be9127"}
|
||||
|
||||
datascript/datascript {:git/url "https://github.com/logseq/datascript" ;; fork
|
||||
:sha "ff5a7d5326e2546f40146e4a489343f557519bc3"}
|
||||
:sha "d6305968aa05bd309abd6d764908cf04ea8000b9"}
|
||||
datascript-transit/datascript-transit {:mvn/version "0.3.0"
|
||||
:exclusions [datascript/datascript]}
|
||||
funcool/promesa {:mvn/version "11.0.678"}
|
||||
|
||||
6
dist/db-worker-node.js
vendored
Executable file
6
dist/db-worker-node.js
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
|
||||
require(path.resolve(__dirname, "../static/db-worker-node.js"));
|
||||
2
dist/logseq.js
vendored
2
dist/logseq.js
vendored
@@ -3,4 +3,4 @@
|
||||
|
||||
const path = require("path");
|
||||
|
||||
require(path.resolve(__dirname, "./logseq-cli.js"));
|
||||
require(path.resolve(__dirname, "../static/logseq-cli.js"));
|
||||
|
||||
@@ -65,7 +65,7 @@ Key changes:
|
||||
2. If lock file exists, read port/pid; probe `/healthz` + `/readyz`.
|
||||
3. If healthy, reuse existing server; build the connection URL from localhost and the lock file port.
|
||||
4. If unhealthy or stale, attempt to spawn a new server; if db-worker-node cannot handle the lock situation, CLI repairs the lock then retries.
|
||||
5. Spawn via `child_process.spawn`: `node ./dist/db-worker-node.js --repo <repo> --data-dir <...>`.
|
||||
5. Spawn via `child_process.spawn`: `./dist/db-worker-node.js --repo <repo> --data-dir <...>`.
|
||||
6. Resolve actual port from the lock file written by db-worker-node.
|
||||
- **Connection URL**: derived from the repo lock file; host is always localhost and the port is always discovered from the lock file.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Logseq CLI Datascript Query Implementation Plan
|
||||
|
||||
Goal: Add a logseq-cli query subcommand that runs a Datascript query via db-worker-node and returns a list of block IDs.
|
||||
Architecture: The CLI will parse a query form from arguments, call db-worker-node using the existing /v1/invoke transport with :thread-api/q, and normalize results into a stable list of block IDs.
|
||||
Goal: Add a logseq-cli query subcommand that runs a Datascript query via db-worker-node and returns the raw datascript-query result shape.
|
||||
Architecture: The CLI will parse a query form from arguments, call db-worker-node using the existing /v1/invoke transport with :thread-api/q, and return whatever datascript-query returns without normalization.
|
||||
Architecture: No new db-worker-node HTTP endpoints are required because :thread-api/q already exists in the worker thread API.
|
||||
Tech Stack: ClojureScript, babashka.cli, Datascript, db-worker-node HTTP transport.
|
||||
Related: Relates to docs/agent-guide/012-logseq-cli-graph-storage.md.
|
||||
@@ -9,14 +9,14 @@ Related: Relates to docs/agent-guide/012-logseq-cli-graph-storage.md.
|
||||
## Problem statement
|
||||
|
||||
The current logseq-cli does not expose a query subcommand for running Datascript queries against a graph.
|
||||
Users need a CLI command that executes a Datascript query and returns only the matching block IDs for scripting and downstream tooling.
|
||||
Users need a CLI command that executes a Datascript query and returns the same result shape as datascript-query for scripting and downstream tooling.
|
||||
The solution should follow the existing logseq-cli and db-worker-node invocation patterns so it works with the current daemon and transport.
|
||||
|
||||
## Testing Plan
|
||||
|
||||
I will add an integration test that creates a graph, inserts blocks, runs the new query subcommand, and asserts that the returned IDs match the expected block IDs.
|
||||
I will add a unit test that validates query argument parsing, including invalid EDN, missing query text, and optional inputs parsing.
|
||||
I will add a unit test that verifies result normalization from the raw query result to a vector of block IDs.
|
||||
I will add a unit test that verifies the query command returns the same shape as datascript-query without transformation.
|
||||
I will follow @test-driven-development and write the failing tests before implementing behavior.
|
||||
|
||||
NOTE: I will write *all* tests before I add any implementation behavior.
|
||||
@@ -29,9 +29,8 @@ Return a structured action map that includes :type :query, :repo, :query, and :i
|
||||
Register the new command in src/main/logseq/cli/commands.cljs and include it in the command table so help output includes query.
|
||||
Update src/main/logseq/cli/main.cljs usage text to include query in the command list.
|
||||
Implement execution in src/main/logseq/cli/command/query.cljs using logseq.cli.transport/invoke with :thread-api/q and args [repo [query & inputs]].
|
||||
Normalize the raw Datascript result into a vector of block IDs by accepting numbers or entities with :db/id, and raise an error when no IDs can be derived.
|
||||
Ensure output is stable by sorting numeric IDs ascending and removing duplicates before returning.
|
||||
Add formatting in src/main/logseq/cli/format.cljs for :query to render a single-column table of IDs in human output and a vector in json or edn output.
|
||||
Return the raw Datascript result as-is, matching datascript-query output across human, json, and edn formats.
|
||||
Add formatting in src/main/logseq/cli/format.cljs for :query to render the raw result in human output and pass-through for json or edn output.
|
||||
Add command-level validation in src/main/logseq/cli/commands.cljs to return a missing-query error when no query is supplied.
|
||||
Update src/test/logseq/cli/commands_test.cljs to expect query in help output and to validate parse errors for missing query or invalid input.
|
||||
Add a CLI integration test in src/test/logseq/cli/integration_test.cljs that uses run-cli to execute query and verifies IDs in JSON output.
|
||||
@@ -40,14 +39,13 @@ Confirm that no db-worker-node changes are required by verifying that :thread-ap
|
||||
## Edge cases
|
||||
|
||||
A query string that cannot be read as EDN should return a clear invalid-options error and a non-zero exit code.
|
||||
A query that returns no results should return an empty ID list with a successful status.
|
||||
A query that returns non-entity values should error if no block IDs can be extracted from the result set.
|
||||
A query that returns no results should return an empty result with a successful status.
|
||||
Queries with :in parameters should work when --inputs supplies the matching values in order.
|
||||
|
||||
## Testing Details
|
||||
|
||||
The integration test will create a graph, add known blocks, run a query that finds those blocks, and verify that the output vector contains their db/id values and only those values.
|
||||
The unit tests will assert that parsing rejects invalid EDN for --inputs, that a missing query produces a :missing-query error, that result normalization handles tuples and entity maps into a flat vector of IDs, and that it errors when no IDs can be extracted.
|
||||
The integration test will create a graph, add known blocks, run a query that finds those blocks, and verify that the output matches the datascript-query result shape.
|
||||
The unit tests will assert that parsing rejects invalid EDN for --inputs, that a missing query produces a :missing-query error, and that query execution returns raw results unchanged.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
@@ -56,14 +54,13 @@ The unit tests will assert that parsing rejects invalid EDN for --inputs, that a
|
||||
- Add output formatting in src/main/logseq/cli/format.cljs.
|
||||
- Update usage text in src/main/logseq/cli/main.cljs.
|
||||
- Use transport/invoke with :thread-api/q and [repo [query & inputs]].
|
||||
- Normalize results into unique, sorted numeric IDs.
|
||||
- Return datascript-query results without transformation.
|
||||
- Keep all argument parsing and validation inside query command module using --query and --inputs.
|
||||
- Keep db-worker-node changes to zero unless a new worker API is required.
|
||||
|
||||
## Question
|
||||
|
||||
Use --query and --inputs options for the query subcommand.
|
||||
Output should be sorted and de-duplicated for scripting stability.
|
||||
Command should error when no block IDs can be extracted.
|
||||
Output should mirror datascript-query for scripting stability.
|
||||
|
||||
---
|
||||
|
||||
@@ -126,7 +126,7 @@ Node runtime must not use OPFS or sqlite-wasm. Instead, use `better-sqlite3` as
|
||||
The db-worker should be runnable as a standalone process for Node.js environments.
|
||||
|
||||
### Entry Point
|
||||
- Provide a CLI entry (example: `bin/logseq-db-worker` or `node dist/db-worker-node.js`).
|
||||
- Provide a CLI entry (example: `bin/logseq-db-worker` or `./dist/db-worker-node.js`).
|
||||
- CLI flags (suggested):
|
||||
- Binds to localhost on a random port and records it in the repo lock file.
|
||||
- `--data-dir` (path for sqlite files, required or default to `~/.logseq/cli-graphs`)
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
"logseq": "dist/logseq.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/db-worker-node.js",
|
||||
"dist/logseq-cli.js"
|
||||
"dist/logseq.js",
|
||||
"static/db-worker-node.js",
|
||||
"static/logseq-cli.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=22.20.0"
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
:loader-mode :eval}}
|
||||
|
||||
:db-worker-node {:target :node-script
|
||||
:output-to "dist/db-worker-node.js"
|
||||
:output-to "static/db-worker-node.js"
|
||||
:main frontend.worker.db-worker-node/main
|
||||
:compiler-options {:infer-externs :auto
|
||||
:source-map true
|
||||
@@ -96,7 +96,7 @@
|
||||
:redef false}}}
|
||||
|
||||
:logseq-cli {:target :node-script
|
||||
:output-to "dist/logseq-cli.js"
|
||||
:output-to "static/logseq-cli.js"
|
||||
:main logseq.cli.main/main
|
||||
:compiler-options {:infer-externs :auto
|
||||
:source-map true
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
(defn top-level-summary
|
||||
[table]
|
||||
(let [groups [{:title "Graph Inspect and Edit"
|
||||
:commands #{"list" "add" "remove" "move" "search" "show"}}
|
||||
:commands #{"list" "add" "remove" "move" "search" "query" "show"}}
|
||||
{:title "Graph Management"
|
||||
:commands #{"graph" "server"}}]
|
||||
render-group (fn [{:keys [title commands]}]
|
||||
|
||||
66
src/main/logseq/cli/command/query.cljs
Normal file
66
src/main/logseq/cli/command/query.cljs
Normal file
@@ -0,0 +1,66 @@
|
||||
(ns logseq.cli.command.query
|
||||
"Query-related CLI commands."
|
||||
(:require [clojure.string :as string]
|
||||
[logseq.cli.command.core :as core]
|
||||
[logseq.cli.server :as cli-server]
|
||||
[logseq.cli.transport :as transport]
|
||||
[logseq.common.util :as common-util]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(def ^:private query-spec
|
||||
{:query {:desc "Datascript query EDN"}
|
||||
:inputs {:desc "EDN vector of query inputs"}})
|
||||
|
||||
(def entries
|
||||
[(core/command-entry ["query"] :query "Run a Datascript query" query-spec)])
|
||||
|
||||
(defn- parse-edn
|
||||
[label value]
|
||||
(let [parsed (common-util/safe-read-string {:log-error? false} value)]
|
||||
(if (nil? parsed)
|
||||
{:ok? false
|
||||
:error {:code :invalid-options
|
||||
:message (str "invalid " label " edn")}}
|
||||
{:ok? true :value parsed})))
|
||||
|
||||
(defn build-action
|
||||
[options repo]
|
||||
(if-not (seq repo)
|
||||
{:ok? false
|
||||
:error {:code :missing-repo
|
||||
:message "repo is required for query"}}
|
||||
(let [query-text (some-> (:query options) string/trim)]
|
||||
(if-not (seq query-text)
|
||||
{:ok? false
|
||||
:error {:code :missing-query
|
||||
:message "query is required"}}
|
||||
(let [query-result (parse-edn "query" query-text)]
|
||||
(if-not (:ok? query-result)
|
||||
query-result
|
||||
(let [inputs-text (some-> (:inputs options) string/trim)
|
||||
inputs-result (when (seq inputs-text)
|
||||
(parse-edn "inputs" inputs-text))]
|
||||
(cond
|
||||
(and inputs-result (not (:ok? inputs-result)))
|
||||
inputs-result
|
||||
|
||||
(and inputs-result (not (vector? (:value inputs-result))))
|
||||
{:ok? false
|
||||
:error {:code :invalid-options
|
||||
:message "inputs must be a vector"}}
|
||||
|
||||
:else
|
||||
{:ok? true
|
||||
:action {:type :query
|
||||
:repo repo
|
||||
:graph (core/repo->graph repo)
|
||||
:query (:value query-result)
|
||||
:inputs (or (:value inputs-result) [])}}))))))))
|
||||
|
||||
(defn execute-query
|
||||
[action config]
|
||||
(-> (p/let [cfg (cli-server/ensure-server! config (:repo action))
|
||||
args (into [(:query action)] (:inputs action))
|
||||
results (transport/invoke cfg :thread-api/q false [(:repo action) args])]
|
||||
{:status :ok
|
||||
:data {:result results}})))
|
||||
@@ -40,6 +40,7 @@
|
||||
[:db/id
|
||||
:block/uuid
|
||||
:block/title
|
||||
:block/content
|
||||
{:logseq.property/status [:db/ident :block/name :block/title]}
|
||||
:block/order
|
||||
{:block/parent [:db/id]}
|
||||
@@ -49,6 +50,7 @@
|
||||
[:db/id
|
||||
:block/uuid
|
||||
:block/title
|
||||
:block/content
|
||||
{:logseq.property/status [:db/ident :block/name :block/title]}
|
||||
{:block/tags [:db/id :block/name :block/title :block/uuid]}
|
||||
{:block/page [:db/id :block/name :block/title :block/uuid]}
|
||||
@@ -120,11 +122,13 @@
|
||||
(defn- block-label
|
||||
[node]
|
||||
(let [title (:block/title node)
|
||||
content (:block/content node)
|
||||
status (status-label node)
|
||||
uuid->label (:uuid->label node)
|
||||
text (or title content)
|
||||
base (cond
|
||||
(and title (seq status)) (str status " " title)
|
||||
title title
|
||||
(and text (seq status)) (str status " " text)
|
||||
text text
|
||||
(:block/name node) (:block/name node)
|
||||
(:block/uuid node) (some-> (:block/uuid node) str))
|
||||
base (replace-uuid-refs base uuid->label)
|
||||
@@ -138,6 +142,7 @@
|
||||
[node uuid->label]
|
||||
(cond-> node
|
||||
(:block/title node) (update :block/title replace-uuid-refs uuid->label)
|
||||
(:block/content node) (update :block/content replace-uuid-refs uuid->label)
|
||||
(:block/name node) (update :block/name replace-uuid-refs uuid->label)
|
||||
(:block/children node) (update :block/children (fn [children]
|
||||
(mapv #(resolve-uuid-refs-in-node % uuid->label) children)))
|
||||
@@ -264,7 +269,7 @@
|
||||
ref-blocks (:blocks linked-refs)
|
||||
pages (keep :block/page ref-blocks)
|
||||
texts (->> (concat nodes ref-blocks pages)
|
||||
(mapcat (fn [node] (keep node [:block/title :block/name])))
|
||||
(mapcat (fn [node] (keep node [:block/title :block/name :block/content])))
|
||||
(remove string/blank?))]
|
||||
(->> texts
|
||||
(mapcat extract-uuid-refs)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[logseq.cli.command.graph :as graph-command]
|
||||
[logseq.cli.command.list :as list-command]
|
||||
[logseq.cli.command.move :as move-command]
|
||||
[logseq.cli.command.query :as query-command]
|
||||
[logseq.cli.command.remove :as remove-command]
|
||||
[logseq.cli.command.search :as search-command]
|
||||
[logseq.cli.command.server :as server-command]
|
||||
@@ -89,6 +90,13 @@
|
||||
:message "search text is required"}
|
||||
:summary summary})
|
||||
|
||||
(defn- missing-query-result
|
||||
[summary]
|
||||
{:ok? false
|
||||
:error {:code :missing-query
|
||||
:message "query is required"}
|
||||
:summary summary})
|
||||
|
||||
;; Error helpers are in logseq.cli.command.core.
|
||||
|
||||
;; Command-specific validation and entries are in subcommand namespaces.
|
||||
@@ -101,6 +109,7 @@
|
||||
move-command/entries
|
||||
remove-command/entries
|
||||
search-command/entries
|
||||
query-command/entries
|
||||
show-command/entries)))
|
||||
|
||||
;; Global option parsing lives in logseq.cli.command.core.
|
||||
@@ -110,7 +119,7 @@
|
||||
(string/join " " (cond-> (vec dispatch)
|
||||
wrong-input (conj wrong-input))))
|
||||
|
||||
(defn- finalize-command
|
||||
(defn- ^:large-vars/cleanup-todo finalize-command
|
||||
[summary {:keys [command opts args cmds spec]}]
|
||||
(let [opts (command-core/normalize-opts opts)
|
||||
args (vec args)
|
||||
@@ -167,6 +176,9 @@
|
||||
(and (= command :search) (not has-args?))
|
||||
(missing-search-result summary)
|
||||
|
||||
(and (= command :query) (not (seq (some-> (:query opts) string/trim))))
|
||||
(missing-query-result summary)
|
||||
|
||||
(and (#{:list-page :list-tag :list-property} command)
|
||||
(list-command/invalid-options? command opts))
|
||||
(command-core/invalid-options-result summary (list-command/invalid-options? command opts))
|
||||
@@ -339,6 +351,9 @@
|
||||
:search
|
||||
(search-command/build-action options args repo)
|
||||
|
||||
:query
|
||||
(query-command/build-action options repo)
|
||||
|
||||
:show
|
||||
(show-command/build-action options repo)
|
||||
|
||||
@@ -376,6 +391,7 @@
|
||||
:remove-block (remove-command/execute-remove action config)
|
||||
:remove-page (remove-command/execute-remove action config)
|
||||
:search (search-command/execute-search action config)
|
||||
:query (query-command/execute-query action config)
|
||||
:show (show-command/execute-show action config)
|
||||
:server-list (server-command/execute-list action config)
|
||||
:server-status (server-command/execute-status action config)
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
:missing-repo "Use --repo <name>"
|
||||
:missing-content "Use --content or pass content as args"
|
||||
:missing-search-text "Provide search text as a positional argument"
|
||||
:missing-query "Use --query <edn>"
|
||||
nil))
|
||||
|
||||
(defn- format-error
|
||||
@@ -184,7 +185,11 @@
|
||||
(mapv (fn [item]
|
||||
[(:db/id item)
|
||||
(or (:title item) (:content item))])
|
||||
(or results []))))
|
||||
(or results []))))
|
||||
|
||||
(defn- format-query-results
|
||||
[result]
|
||||
(pr-str result))
|
||||
|
||||
(defn- format-graph-info
|
||||
[{:keys [graph logseq.kv/graph-created-at logseq.kv/schema-version]} now-ms]
|
||||
@@ -275,6 +280,7 @@
|
||||
:graph-export (format-graph-export context)
|
||||
:graph-import (format-graph-import context)
|
||||
:search (format-search-results (:results data))
|
||||
:query (format-query-results (:result data))
|
||||
:show (or (:message data) (pr-str data))
|
||||
(if (and (map? data) (contains? data :message))
|
||||
(:message data)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
(string/join "\n"
|
||||
["logseq <command> [options]"
|
||||
""
|
||||
"Commands: list page, list tag, list property, add block, add page, move, remove block, remove page, search, show, graph list, graph create, graph switch, graph remove, graph validate, graph info, graph export, graph import, server list, server status, server start, server stop, server restart"
|
||||
"Commands: list page, list tag, list property, add block, add page, move, remove block, remove page, search, query, show, graph list, graph create, graph switch, graph remove, graph validate, graph info, graph export, graph import, server list, server status, server start, server stop, server restart"
|
||||
""
|
||||
"Options:"
|
||||
summary]))
|
||||
|
||||
@@ -165,9 +165,9 @@
|
||||
|
||||
(defn- spawn-server!
|
||||
[{:keys [repo data-dir]}]
|
||||
(let [script (node-path/join js/__dirname "db-worker-node.js")
|
||||
args #js [script "--repo" repo "--data-dir" data-dir]
|
||||
child (.spawn child-process "node" args #js {:detached true
|
||||
(let [script (node-path/join js/__dirname "../dist/db-worker-node.js")
|
||||
args #js ["--repo" repo "--data-dir" data-dir]
|
||||
child (.spawn child-process script args #js {:detached true
|
||||
:stdio "ignore"})]
|
||||
(.unref child)
|
||||
child))
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
|
||||
(deftest db-worker-node-parse-args-ignores-host-and-port
|
||||
(let [parse-args #'db-worker-node/parse-args
|
||||
result (parse-args #js ["node" "db-worker-node.js"
|
||||
result (parse-args #js ["node" "dist/db-worker-node.js"
|
||||
"--host" "0.0.0.0"
|
||||
"--port" "1234"
|
||||
"--repo" "logseq_db_parse_args"
|
||||
|
||||
32
src/test/logseq/cli/command/query_test.cljs
Normal file
32
src/test/logseq/cli/command/query_test.cljs
Normal file
@@ -0,0 +1,32 @@
|
||||
(ns logseq.cli.command.query-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[clojure.string :as string]
|
||||
[logseq.cli.command.query :as query-command]))
|
||||
|
||||
(deftest test-build-action-parses-query
|
||||
(testing "query parses query and inputs"
|
||||
(let [result (query-command/build-action {:query "[:find ?e :in $ ?title :where [?e :block/title ?title]]"
|
||||
:inputs "[\"Hello\"]"}
|
||||
"logseq_db_demo")]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :query (get-in result [:action :type])))
|
||||
(is (= "logseq_db_demo" (get-in result [:action :repo])))
|
||||
(is (= '[:find ?e :in $ ?title :where [?e :block/title ?title]]
|
||||
(get-in result [:action :query])))
|
||||
(is (= ["Hello"] (get-in result [:action :inputs]))))))
|
||||
|
||||
(deftest test-build-action-invalid-edn
|
||||
(testing "invalid query edn returns invalid-options"
|
||||
(let [result (query-command/build-action {:query "[:find ?e"}
|
||||
"logseq_db_demo")]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :invalid-options (get-in result [:error :code])))
|
||||
(is (string/includes? (get-in result [:error :message]) "query"))))
|
||||
|
||||
(testing "invalid inputs edn returns invalid-options"
|
||||
(let [result (query-command/build-action {:query "[:find ?e :where [?e :block/title \"Hello\"]]"
|
||||
:inputs "[\"Hello"}
|
||||
"logseq_db_demo")]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :invalid-options (get-in result [:error :code])))
|
||||
(is (string/includes? (get-in result [:error :message]) "inputs")))))
|
||||
@@ -19,6 +19,7 @@
|
||||
(is (string/includes? summary "remove"))
|
||||
(is (string/includes? summary "move"))
|
||||
(is (string/includes? summary "search"))
|
||||
(is (string/includes? summary "query"))
|
||||
(is (string/includes? summary "show"))
|
||||
(is (string/includes? summary "graph"))
|
||||
(is (string/includes? summary "server"))))
|
||||
@@ -482,6 +483,22 @@
|
||||
(is (= :show (:command result)))
|
||||
(is (= "Home" (get-in result [:options :page-name]))))))
|
||||
|
||||
(deftest test-verb-subcommand-parse-query
|
||||
(testing "query requires query option"
|
||||
(let [result (commands/parse-args ["query"])]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :missing-query (get-in result [:error :code])))))
|
||||
|
||||
(testing "query parses with query and inputs"
|
||||
(let [result (commands/parse-args ["query"
|
||||
"--query" "[:find ?e :where [?e :block/title \"Hello\"]]"
|
||||
"--inputs" "[\"Hello\"]"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :query (:command result)))
|
||||
(is (= "[:find ?e :where [?e :block/title \"Hello\"]]"
|
||||
(get-in result [:options :query])))
|
||||
(is (= "[\"Hello\"]" (get-in result [:options :inputs]))))))
|
||||
|
||||
(deftest test-verb-subcommand-parse-graph-import-export
|
||||
(testing "graph create requires --repo even with positional args"
|
||||
(let [result (commands/parse-args ["graph" "create" "demo"])]
|
||||
|
||||
@@ -200,6 +200,14 @@
|
||||
{:output-format nil})]
|
||||
(is (= "Line 1\nLine 2" result)))))
|
||||
|
||||
(deftest test-human-output-query
|
||||
(testing "query renders raw result"
|
||||
(let [result (format/format-result {:status :ok
|
||||
:command :query
|
||||
:data {:result [[1] [2] [3]]}}
|
||||
{:output-format nil})]
|
||||
(is (= "[[1] [2] [3]]" result)))))
|
||||
|
||||
(deftest test-human-output-error-formatting
|
||||
(testing "errors include code and hint when available"
|
||||
(let [result (format/format-result {:status :error
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
(ns logseq.cli.integration-test
|
||||
(:require [cljs.reader :as reader]
|
||||
(:require ["fs" :as fs]
|
||||
["path" :as node-path]
|
||||
[cljs.reader :as reader]
|
||||
[cljs.test :refer [deftest is async]]
|
||||
[clojure.string :as string]
|
||||
[frontend.test.node-helper :as node-helper]
|
||||
[logseq.cli.main :as cli-main]
|
||||
[promesa.core :as p]
|
||||
["fs" :as fs]
|
||||
["path" :as node-path]))
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn- run-cli
|
||||
[args data-dir cfg-path]
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
(defn- node-title
|
||||
[node]
|
||||
(or (:block/title node) (:title node)))
|
||||
(or (:block/title node) (:block/content node) (:title node) (:content node)))
|
||||
|
||||
(defn- node-uuid
|
||||
[node]
|
||||
@@ -49,456 +49,491 @@
|
||||
node
|
||||
(some #(find-block-by-title % title) (node-children node)))))
|
||||
|
||||
|
||||
(deftest test-cli-graph-list
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
result (run-cli ["graph" "list"] data-dir cfg-path)
|
||||
payload (parse-json-output result)]
|
||||
(is (= 0 (:exit-code result)))
|
||||
(is (= "ok" (:status payload)))
|
||||
(is (contains? payload :data))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
result (run-cli ["graph" "list"] data-dir cfg-path)
|
||||
payload (parse-json-output result)]
|
||||
(is (= 0 (:exit-code result)))
|
||||
(is (= "ok" (:status payload)))
|
||||
(is (contains? payload :data))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-graph-create-and-info
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
create-result (run-cli ["graph" "create" "--repo" "demo-graph"] data-dir cfg-path)
|
||||
create-payload (parse-json-output create-result)
|
||||
info-result (run-cli ["graph" "info"] data-dir cfg-path)
|
||||
info-payload (parse-json-output info-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "demo-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= 0 (:exit-code create-result)))
|
||||
(is (= "ok" (:status create-payload)))
|
||||
(is (= 0 (:exit-code info-result)))
|
||||
(is (= "ok" (:status info-payload)))
|
||||
(is (= "demo-graph" (get-in info-payload [:data :graph])))
|
||||
(is (= 0 (:exit-code stop-result)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
create-result (run-cli ["graph" "create" "--repo" "demo-graph"] data-dir cfg-path)
|
||||
create-payload (parse-json-output create-result)
|
||||
info-result (run-cli ["graph" "info"] data-dir cfg-path)
|
||||
info-payload (parse-json-output info-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "demo-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= 0 (:exit-code create-result)))
|
||||
(is (= "ok" (:status create-payload)))
|
||||
(is (= 0 (:exit-code info-result)))
|
||||
(is (= "ok" (:status info-payload)))
|
||||
(is (= "demo-graph" (get-in info-payload [:data :graph])))
|
||||
(is (= 0 (:exit-code stop-result)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-list-add-search-show-remove
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "content-graph"] data-dir cfg-path)
|
||||
add-page-result (run-cli ["--repo" "content-graph" "add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
add-page-payload (parse-json-output add-page-result)
|
||||
list-page-result (run-cli ["--repo" "content-graph" "list" "page"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
list-tag-result (run-cli ["--repo" "content-graph" "list" "tag"] data-dir cfg-path)
|
||||
list-tag-payload (parse-json-output list-tag-result)
|
||||
list-property-result (run-cli ["--repo" "content-graph" "list" "property"] data-dir cfg-path)
|
||||
list-property-payload (parse-json-output list-property-result)
|
||||
add-block-result (run-cli ["--repo" "content-graph" "add" "block" "--target-page-name" "TestPage" "--content" "Test block"] data-dir cfg-path)
|
||||
add-block-payload (parse-json-output add-block-result)
|
||||
_ (p/delay 100)
|
||||
search-result (run-cli ["--repo" "content-graph" "search" "t"] data-dir cfg-path)
|
||||
search-payload (parse-json-output search-result)
|
||||
show-result (run-cli ["--repo" "content-graph" "show" "--page-name" "TestPage" "--format" "json"] data-dir cfg-path)
|
||||
show-payload (parse-json-output show-result)
|
||||
remove-page-result (run-cli ["--repo" "content-graph" "remove" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
remove-page-payload (parse-json-output remove-page-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "content-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= 0 (:exit-code add-page-result)))
|
||||
(is (= "ok" (:status add-page-payload)))
|
||||
(is (= "ok" (:status add-block-payload)))
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (vector? (get-in list-page-payload [:data :items])))
|
||||
(is (= "ok" (:status list-tag-payload)))
|
||||
(is (vector? (get-in list-tag-payload [:data :items])))
|
||||
(is (= "ok" (:status list-property-payload)))
|
||||
(is (vector? (get-in list-property-payload [:data :items])))
|
||||
(is (= "ok" (:status search-payload)))
|
||||
(is (vector? (get-in search-payload [:data :results])))
|
||||
(let [types (set (map :type (get-in search-payload [:data :results])))]
|
||||
(is (contains? types "page"))
|
||||
(is (contains? types "block"))
|
||||
(is (contains? types "tag"))
|
||||
(is (contains? types "property")))
|
||||
(is (= "ok" (:status show-payload)))
|
||||
(is (contains? (get-in show-payload [:data :root]) :uuid))
|
||||
(is (= "ok" (:status remove-page-payload)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "content-graph"] data-dir cfg-path)
|
||||
add-page-result (run-cli ["--repo" "content-graph" "add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
add-page-payload (parse-json-output add-page-result)
|
||||
list-page-result (run-cli ["--repo" "content-graph" "list" "page"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
list-tag-result (run-cli ["--repo" "content-graph" "list" "tag"] data-dir cfg-path)
|
||||
list-tag-payload (parse-json-output list-tag-result)
|
||||
list-property-result (run-cli ["--repo" "content-graph" "list" "property"] data-dir cfg-path)
|
||||
list-property-payload (parse-json-output list-property-result)
|
||||
add-block-result (run-cli ["--repo" "content-graph" "add" "block" "--target-page-name" "TestPage" "--content" "Test block"] data-dir cfg-path)
|
||||
add-block-payload (parse-json-output add-block-result)
|
||||
_ (p/delay 100)
|
||||
search-result (run-cli ["--repo" "content-graph" "search" "t"] data-dir cfg-path)
|
||||
search-payload (parse-json-output search-result)
|
||||
show-result (run-cli ["--repo" "content-graph" "show" "--page-name" "TestPage" "--format" "json"] data-dir cfg-path)
|
||||
show-payload (parse-json-output show-result)
|
||||
remove-page-result (run-cli ["--repo" "content-graph" "remove" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
remove-page-payload (parse-json-output remove-page-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "content-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= 0 (:exit-code add-page-result)))
|
||||
(is (= "ok" (:status add-page-payload)))
|
||||
(is (= "ok" (:status add-block-payload)))
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (vector? (get-in list-page-payload [:data :items])))
|
||||
(is (= "ok" (:status list-tag-payload)))
|
||||
(is (vector? (get-in list-tag-payload [:data :items])))
|
||||
(is (= "ok" (:status list-property-payload)))
|
||||
(is (vector? (get-in list-property-payload [:data :items])))
|
||||
(is (= "ok" (:status search-payload)))
|
||||
(is (vector? (get-in search-payload [:data :results])))
|
||||
(let [types (set (map :type (get-in search-payload [:data :results])))]
|
||||
(is (contains? types "page"))
|
||||
(is (contains? types "block"))
|
||||
(is (contains? types "tag"))
|
||||
(is (contains? types "property")))
|
||||
(is (= "ok" (:status show-payload)))
|
||||
(is (contains? (get-in show-payload [:data :root]) :uuid))
|
||||
(is (= "ok" (:status remove-page-payload)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-query
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-query")
|
||||
query-text "[:find ?e :in $ ?title :where [?e :block/title ?title]]"]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
create-result (run-cli ["graph" "create" "--repo" "query-graph"] data-dir cfg-path)
|
||||
create-payload (parse-json-output create-result)
|
||||
_ (run-cli ["--repo" "query-graph" "add" "page" "--page" "QueryPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "query-graph" "add" "block" "--target-page-name" "QueryPage" "--content" "Query block"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "query-graph" "add" "block" "--target-page-name" "QueryPage" "--content" "Query block"] data-dir cfg-path)
|
||||
_ (p/delay 100)
|
||||
query-result (run-cli ["--repo" "query-graph"
|
||||
"query"
|
||||
"--query" query-text
|
||||
"--inputs" "[\"Query block\"]"]
|
||||
data-dir cfg-path)
|
||||
query-payload (parse-json-output query-result)
|
||||
result (get-in query-payload [:data :result])
|
||||
stop-result (run-cli ["server" "stop" "--repo" "query-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status create-payload)))
|
||||
(is (= 0 (:exit-code query-result)))
|
||||
(is (= "ok" (:status query-payload)))
|
||||
(is (vector? result))
|
||||
(is (= 2 (count result)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-show-search-resolve-nested-uuid-refs
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-nested-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "nested-refs"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "page" "--page" "NestedPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage" "--content" "Inner"] data-dir cfg-path)
|
||||
show-inner (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-inner-payload (parse-json-output show-inner)
|
||||
inner-node (find-block-by-title (get-in show-inner-payload [:data :root]) "Inner")
|
||||
inner-uuid (node-uuid inner-node)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage"
|
||||
"--content" (str "See [[" inner-uuid "]]")] data-dir cfg-path)
|
||||
show-middle (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-middle-payload (parse-json-output show-middle)
|
||||
middle-node (find-block-by-title (get-in show-middle-payload [:data :root]) "See [[Inner]]")
|
||||
middle-uuid (node-uuid middle-node)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage"
|
||||
"--content" (str "Outer [[" middle-uuid "]]")] data-dir cfg-path)
|
||||
show-outer (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-outer-payload (parse-json-output show-outer)
|
||||
outer-node (find-block-by-title (get-in show-outer-payload [:data :root]) "Outer [[See [[Inner]]]]")
|
||||
search-result (run-cli ["--repo" "nested-refs" "search" "Outer"] data-dir cfg-path)
|
||||
search-payload (parse-json-output search-result)
|
||||
search-item (some (fn [item]
|
||||
(when (and (string? (:content item))
|
||||
(string/includes? (:content item) "Outer"))
|
||||
item))
|
||||
(get-in search-payload [:data :results]))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "nested-refs"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? inner-uuid))
|
||||
(is (some? middle-uuid))
|
||||
(is (some? outer-node))
|
||||
(is (= "Outer [[See [[Inner]]]]" (:content search-item)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-nested-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "nested-refs"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "page" "--page" "NestedPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage" "--content" "Inner"] data-dir cfg-path)
|
||||
show-inner (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-inner-payload (parse-json-output show-inner)
|
||||
inner-node (find-block-by-title (get-in show-inner-payload [:data :root]) "Inner")
|
||||
inner-uuid (node-uuid inner-node)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage"
|
||||
"--content" (str "See [[" inner-uuid "]]")] data-dir cfg-path)
|
||||
show-middle (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-middle-payload (parse-json-output show-middle)
|
||||
middle-node (find-block-by-title (get-in show-middle-payload [:data :root]) "See [[Inner]]")
|
||||
middle-uuid (node-uuid middle-node)
|
||||
_ (run-cli ["--repo" "nested-refs" "add" "block" "--target-page-name" "NestedPage"
|
||||
"--content" (str "Outer [[" middle-uuid "]]")] data-dir cfg-path)
|
||||
show-outer (run-cli ["--repo" "nested-refs" "show" "--page-name" "NestedPage" "--format" "json"] data-dir cfg-path)
|
||||
show-outer-payload (parse-json-output show-outer)
|
||||
outer-node (find-block-by-title (get-in show-outer-payload [:data :root]) "Outer [[See [[Inner]]]]")
|
||||
search-result (run-cli ["--repo" "nested-refs" "search" "Outer"] data-dir cfg-path)
|
||||
search-payload (parse-json-output search-result)
|
||||
search-item (some (fn [item]
|
||||
(when (and (string? (:content item))
|
||||
(string/includes? (:content item) "Outer"))
|
||||
item))
|
||||
(get-in search-payload [:data :results]))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "nested-refs"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? inner-uuid))
|
||||
(is (some? middle-uuid))
|
||||
(is (some? outer-node))
|
||||
(is (= "Outer [[See [[Inner]]]]" (:content search-item)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-show-linked-references-json
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-linked-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
target-show-before (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-before-payload (parse-json-output target-show-before)
|
||||
target-uuid (or (get-in target-before-payload [:data :root :block/uuid])
|
||||
(get-in target-before-payload [:data :root :uuid]))
|
||||
ref-content (str "See [[" target-uuid "]]")
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "block" "--target-page-name" "SourcePage" "--content" ref-content] data-dir cfg-path)
|
||||
source-show (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "SourcePage" "--format" "json"] data-dir cfg-path)
|
||||
source-payload (parse-json-output source-show)
|
||||
ref-node (find-block-by-title (get-in source-payload [:data :root]) ref-content)
|
||||
ref-uuid (or (:block/uuid ref-node) (:uuid ref-node))
|
||||
target-show (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-payload (parse-json-output target-show)
|
||||
linked-refs (get-in target-payload [:data :linked-references])
|
||||
linked-blocks (:blocks linked-refs)
|
||||
linked-uuids (set (map (fn [block]
|
||||
(or (:block/uuid block) (:uuid block)))
|
||||
linked-blocks))
|
||||
linked-page-titles (set (keep (fn [block]
|
||||
(or (get-in block [:block/page :block/title])
|
||||
(get-in block [:block/page :block/name])
|
||||
(get-in block [:page :title])
|
||||
(get-in block [:page :name])))
|
||||
linked-blocks))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? target-uuid))
|
||||
(is (= "ok" (:status target-payload)))
|
||||
(is (some? ref-uuid))
|
||||
(is (contains? linked-uuids ref-uuid))
|
||||
(is (contains? linked-page-titles "SourcePage"))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-linked-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
target-show-before (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-before-payload (parse-json-output target-show-before)
|
||||
target-uuid (or (get-in target-before-payload [:data :root :block/uuid])
|
||||
(get-in target-before-payload [:data :root :uuid]))
|
||||
target-title (or (get-in target-before-payload [:data :root :block/title])
|
||||
(get-in target-before-payload [:data :root :block/name])
|
||||
"TargetPage")
|
||||
ref-content (str "See [[" target-uuid "]]")
|
||||
ref-title (str "See [[" target-title "]]")
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "block" "--target-page-name" "SourcePage" "--content" ref-content] data-dir cfg-path)
|
||||
source-show (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "SourcePage" "--format" "json"] data-dir cfg-path)
|
||||
source-payload (parse-json-output source-show)
|
||||
ref-node (find-block-by-title (get-in source-payload [:data :root]) ref-title)
|
||||
ref-uuid (or (:block/uuid ref-node) (:uuid ref-node))
|
||||
target-show (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-payload (parse-json-output target-show)
|
||||
linked-refs (get-in target-payload [:data :linked-references])
|
||||
linked-blocks (:blocks linked-refs)
|
||||
linked-uuids (set (map (fn [block]
|
||||
(or (:block/uuid block) (:uuid block)))
|
||||
linked-blocks))
|
||||
linked-page-titles (set (keep (fn [block]
|
||||
(or (get-in block [:block/page :block/title])
|
||||
(get-in block [:block/page :block/name])
|
||||
(get-in block [:page :title])
|
||||
(get-in block [:page :name])))
|
||||
linked-blocks))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? target-uuid))
|
||||
(is (= "ok" (:status target-payload)))
|
||||
(is (some? ref-uuid))
|
||||
(is (contains? linked-uuids ref-uuid))
|
||||
(is (contains? linked-page-titles "SourcePage"))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-move-block
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-move")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "move-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "block" "--target-page-name" "SourcePage" "--content" "Parent Block"] data-dir cfg-path)
|
||||
source-show (run-cli ["--repo" "move-graph" "show" "--page-name" "SourcePage" "--format" "json"] data-dir cfg-path)
|
||||
source-payload (parse-json-output source-show)
|
||||
parent-node (find-block-by-title (get-in source-payload [:data :root]) "Parent Block")
|
||||
parent-uuid (or (:block/uuid parent-node) (:uuid parent-node))
|
||||
_ (run-cli ["--repo" "move-graph" "add" "block" "--target-uuid" (str parent-uuid) "--content" "Child Block"] data-dir cfg-path)
|
||||
move-result (run-cli ["--repo" "move-graph" "move" "--uuid" (str parent-uuid) "--target-page-name" "TargetPage"] data-dir cfg-path)
|
||||
move-payload (parse-json-output move-result)
|
||||
target-show (run-cli ["--repo" "move-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-payload (parse-json-output target-show)
|
||||
moved-node (find-block-by-title (get-in target-payload [:data :root]) "Parent Block")
|
||||
child-node (find-block-by-title moved-node "Child Block")
|
||||
stop-result (run-cli ["server" "stop" "--repo" "move-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status move-payload)))
|
||||
(is (some? parent-uuid))
|
||||
(is (some? moved-node))
|
||||
(is (some? child-node))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-move")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "move-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "move-graph" "add" "block" "--target-page-name" "SourcePage" "--content" "Parent Block"] data-dir cfg-path)
|
||||
source-show (run-cli ["--repo" "move-graph" "show" "--page-name" "SourcePage" "--format" "json"] data-dir cfg-path)
|
||||
source-payload (parse-json-output source-show)
|
||||
parent-node (find-block-by-title (get-in source-payload [:data :root]) "Parent Block")
|
||||
parent-uuid (or (:block/uuid parent-node) (:uuid parent-node))
|
||||
_ (run-cli ["--repo" "move-graph" "add" "block" "--target-uuid" (str parent-uuid) "--content" "Child Block"] data-dir cfg-path)
|
||||
move-result (run-cli ["--repo" "move-graph" "move" "--uuid" (str parent-uuid) "--target-page-name" "TargetPage"] data-dir cfg-path)
|
||||
move-payload (parse-json-output move-result)
|
||||
target-show (run-cli ["--repo" "move-graph" "show" "--page-name" "TargetPage" "--format" "json"] data-dir cfg-path)
|
||||
target-payload (parse-json-output target-show)
|
||||
moved-node (find-block-by-title (get-in target-payload [:data :root]) "Parent Block")
|
||||
child-node (find-block-by-title moved-node "Child Block")
|
||||
stop-result (run-cli ["server" "stop" "--repo" "move-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status move-payload)))
|
||||
(is (some? parent-uuid))
|
||||
(is (some? moved-node))
|
||||
(is (some? child-node))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-add-block-pos-ordering
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-add-pos")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "add-pos-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "page" "--page" "PosPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-page-name" "PosPage" "--content" "Parent"] data-dir cfg-path)
|
||||
parent-show (run-cli ["--repo" "add-pos-graph" "show" "--page-name" "PosPage" "--format" "json"] data-dir cfg-path)
|
||||
parent-payload (parse-json-output parent-show)
|
||||
parent-node (find-block-by-title (get-in parent-payload [:data :root]) "Parent")
|
||||
parent-uuid (or (:block/uuid parent-node) (:uuid parent-node))
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-uuid" (str parent-uuid) "--pos" "first-child" "--content" "First"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-uuid" (str parent-uuid) "--pos" "last-child" "--content" "Last"] data-dir cfg-path)
|
||||
final-show (run-cli ["--repo" "add-pos-graph" "show" "--page-name" "PosPage" "--format" "json"] data-dir cfg-path)
|
||||
final-payload (parse-json-output final-show)
|
||||
final-parent (find-block-by-title (get-in final-payload [:data :root]) "Parent")
|
||||
child-titles (map node-title (node-children final-parent))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "add-pos-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? parent-uuid))
|
||||
(is (= ["First" "Last"] (vec child-titles)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-add-pos")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "add-pos-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "page" "--page" "PosPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-page-name" "PosPage" "--content" "Parent"] data-dir cfg-path)
|
||||
parent-show (run-cli ["--repo" "add-pos-graph" "show" "--page-name" "PosPage" "--format" "json"] data-dir cfg-path)
|
||||
parent-payload (parse-json-output parent-show)
|
||||
parent-node (find-block-by-title (get-in parent-payload [:data :root]) "Parent")
|
||||
parent-uuid (or (:block/uuid parent-node) (:uuid parent-node))
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-uuid" (str parent-uuid) "--pos" "first-child" "--content" "First"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "add-pos-graph" "add" "block" "--target-uuid" (str parent-uuid) "--pos" "last-child" "--content" "Last"] data-dir cfg-path)
|
||||
final-show (run-cli ["--repo" "add-pos-graph" "show" "--page-name" "PosPage" "--format" "json"] data-dir cfg-path)
|
||||
final-payload (parse-json-output final-show)
|
||||
final-parent (find-block-by-title (get-in final-payload [:data :root]) "Parent")
|
||||
child-titles (map node-title (node-children final-parent))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "add-pos-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (some? parent-uuid))
|
||||
(is (= ["First" "Last"] (vec child-titles)))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-output-formats-graph-list
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
json-result (run-cli ["graph" "list" "--output" "json"] data-dir cfg-path)
|
||||
json-payload (parse-json-output json-result)
|
||||
edn-result (run-cli ["graph" "list" "--output" "edn"] data-dir cfg-path)
|
||||
edn-payload (parse-edn-output edn-result)
|
||||
human-result (run-cli ["graph" "list" "--output" "human"] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code json-result)))
|
||||
(is (= "ok" (:status json-payload)))
|
||||
(is (= 0 (:exit-code edn-result)))
|
||||
(is (= :ok (:status edn-payload)))
|
||||
(is (not (string/starts-with? (:output human-result) "{:status")))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
json-result (run-cli ["graph" "list" "--output" "json"] data-dir cfg-path)
|
||||
json-payload (parse-json-output json-result)
|
||||
edn-result (run-cli ["graph" "list" "--output" "edn"] data-dir cfg-path)
|
||||
edn-payload (parse-edn-output edn-result)
|
||||
human-result (run-cli ["graph" "list" "--output" "human"] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code json-result)))
|
||||
(is (= "ok" (:status json-payload)))
|
||||
(is (= 0 (:exit-code edn-result)))
|
||||
(is (= :ok (:status edn-payload)))
|
||||
(is (not (string/starts-with? (:output human-result) "{:status")))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-list-outputs-include-id
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "list-id-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
list-tag-result (run-cli ["list" "tag"] data-dir cfg-path)
|
||||
list-tag-payload (parse-json-output list-tag-result)
|
||||
list-property-result (run-cli ["list" "property"] data-dir cfg-path)
|
||||
list-property-payload (parse-json-output list-property-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "list-id-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-page-payload [:data :items])))
|
||||
(is (= "ok" (:status list-tag-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-tag-payload [:data :items])))
|
||||
(is (= "ok" (:status list-property-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-property-payload [:data :items])))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "list-id-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
list-tag-result (run-cli ["list" "tag"] data-dir cfg-path)
|
||||
list-tag-payload (parse-json-output list-tag-result)
|
||||
list-property-result (run-cli ["list" "property"] data-dir cfg-path)
|
||||
list-property-payload (parse-json-output list-property-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "list-id-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-page-payload [:data :items])))
|
||||
(is (= "ok" (:status list-tag-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-tag-payload [:data :items])))
|
||||
(is (= "ok" (:status list-property-payload)))
|
||||
(is (every? #(contains? % :id) (get-in list-property-payload [:data :items])))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-list-page-human-output
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "human-list-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page" "--output" "human"] data-dir cfg-path)
|
||||
output (:output list-page-result)]
|
||||
(is (= 0 (:exit-code list-page-result)))
|
||||
(is (string/includes? output "TITLE"))
|
||||
(is (string/includes? output "TestPage"))
|
||||
(is (string/includes? output "Count:"))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "human-list-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page" "--output" "human"] data-dir cfg-path)
|
||||
output (:output list-page-result)]
|
||||
(is (= 0 (:exit-code list-page-result)))
|
||||
(is (string/includes? output "TITLE"))
|
||||
(is (string/includes? output "TestPage"))
|
||||
(is (string/includes? output "Count:"))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-show-page-block-by-id-and-uuid
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "show-page-block-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page" "--expand"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
page-item (some (fn [item]
|
||||
(when (= "TestPage" (or (:block/title item) (:title item)))
|
||||
item))
|
||||
(get-in list-page-payload [:data :items]))
|
||||
page-id (or (:db/id page-item) (:id page-item))
|
||||
page-uuid (or (:block/uuid page-item) (:uuid page-item))
|
||||
show-by-id-result (run-cli ["show" "--id" (str page-id) "--format" "json"] data-dir cfg-path)
|
||||
show-by-id-payload (parse-json-output show-by-id-result)
|
||||
show-by-uuid-result (run-cli ["show" "--uuid" (str page-uuid) "--format" "json"] data-dir cfg-path)
|
||||
show-by-uuid-payload (parse-json-output show-by-uuid-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "show-page-block-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (some? page-item))
|
||||
(is (some? page-id))
|
||||
(is (some? page-uuid))
|
||||
(is (= "ok" (:status show-by-id-payload)))
|
||||
(is (= (str page-uuid) (str (or (get-in show-by-id-payload [:data :root :uuid])
|
||||
(get-in show-by-id-payload [:data :root :block/uuid])))))
|
||||
(is (= "ok" (:status show-by-uuid-payload)))
|
||||
(is (= (str page-uuid) (str (or (get-in show-by-uuid-payload [:data :root :uuid])
|
||||
(get-in show-by-uuid-payload [:data :root :block/uuid])))))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "show-page-block-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["add" "page" "--page" "TestPage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["list" "page" "--expand"] data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
page-item (some (fn [item]
|
||||
(when (= "TestPage" (or (:block/title item) (:title item)))
|
||||
item))
|
||||
(get-in list-page-payload [:data :items]))
|
||||
page-id (or (:db/id page-item) (:id page-item))
|
||||
page-uuid (or (:block/uuid page-item) (:uuid page-item))
|
||||
show-by-id-result (run-cli ["show" "--id" (str page-id) "--format" "json"] data-dir cfg-path)
|
||||
show-by-id-payload (parse-json-output show-by-id-result)
|
||||
show-by-uuid-result (run-cli ["show" "--uuid" (str page-uuid) "--format" "json"] data-dir cfg-path)
|
||||
show-by-uuid-payload (parse-json-output show-by-uuid-result)
|
||||
stop-result (run-cli ["server" "stop" "--repo" "show-page-block-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status list-page-payload)))
|
||||
(is (some? page-item))
|
||||
(is (some? page-id))
|
||||
(is (some? page-uuid))
|
||||
(is (= "ok" (:status show-by-id-payload)))
|
||||
(is (= (str page-uuid) (str (or (get-in show-by-id-payload [:data :root :uuid])
|
||||
(get-in show-by-id-payload [:data :root :block/uuid])))))
|
||||
(is (= "ok" (:status show-by-uuid-payload)))
|
||||
(is (= (str page-uuid) (str (or (get-in show-by-uuid-payload [:data :root :uuid])
|
||||
(get-in show-by-uuid-payload [:data :root :block/uuid])))))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-show-linked-references
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-linked-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["--repo" "linked-refs-graph" "list" "page" "--expand"]
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-linked-refs")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
_ (run-cli ["graph" "create" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "TargetPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "page" "--page" "SourcePage"] data-dir cfg-path)
|
||||
list-page-result (run-cli ["--repo" "linked-refs-graph" "list" "page" "--expand"]
|
||||
data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
page-item (some (fn [item]
|
||||
(when (= "TargetPage" (or (:block/title item) (:title item)))
|
||||
item))
|
||||
(get-in list-page-payload [:data :items]))
|
||||
page-id (or (:db/id page-item) (:id page-item))
|
||||
blocks-edn (str "[{:block/title \"Ref to TargetPage\" :block/refs [{:db/id " page-id "}]}]")
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "block" "--target-page-name" "SourcePage"
|
||||
"--blocks" blocks-edn] data-dir cfg-path)
|
||||
show-result (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"]
|
||||
data-dir cfg-path)
|
||||
list-page-payload (parse-json-output list-page-result)
|
||||
page-item (some (fn [item]
|
||||
(when (= "TargetPage" (or (:block/title item) (:title item)))
|
||||
item))
|
||||
(get-in list-page-payload [:data :items]))
|
||||
page-id (or (:db/id page-item) (:id page-item))
|
||||
blocks-edn (str "[{:block/title \"Ref to TargetPage\" :block/refs [{:db/id " page-id "}]}]")
|
||||
_ (run-cli ["--repo" "linked-refs-graph" "add" "block" "--target-page-name" "SourcePage"
|
||||
"--blocks" blocks-edn] data-dir cfg-path)
|
||||
show-result (run-cli ["--repo" "linked-refs-graph" "show" "--page-name" "TargetPage" "--format" "json"]
|
||||
data-dir cfg-path)
|
||||
show-payload (parse-json-output show-result)
|
||||
linked (get-in show-payload [:data :linked-references])
|
||||
ref-block (first (:blocks linked))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status show-payload)))
|
||||
(is (some? page-id))
|
||||
(is (map? linked))
|
||||
(is (pos? (:count linked)))
|
||||
(is (seq (:blocks linked)))
|
||||
(is (some? ref-block))
|
||||
(is (some? (or (:block/uuid ref-block) (:uuid ref-block))))
|
||||
(is (some? (or (get-in ref-block [:page :title])
|
||||
(get-in ref-block [:page :name]))))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
show-payload (parse-json-output show-result)
|
||||
linked (get-in show-payload [:data :linked-references])
|
||||
ref-block (first (:blocks linked))
|
||||
stop-result (run-cli ["server" "stop" "--repo" "linked-refs-graph"] data-dir cfg-path)
|
||||
stop-payload (parse-json-output stop-result)]
|
||||
(is (= "ok" (:status show-payload)))
|
||||
(is (some? page-id))
|
||||
(is (map? linked))
|
||||
(is (pos? (:count linked)))
|
||||
(is (seq (:blocks linked)))
|
||||
(is (some? ref-block))
|
||||
(is (some? (or (:block/uuid ref-block) (:uuid ref-block))))
|
||||
(is (some? (or (get-in ref-block [:page :title])
|
||||
(get-in ref-block [:page :name]))))
|
||||
(is (= "ok" (:status stop-payload)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-graph-export-import-edn
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-export-edn")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
export-graph "export-edn-graph"
|
||||
import-graph "import-edn-graph"
|
||||
export-path (node-path/join (node-helper/create-tmp-dir "exports") "graph.edn")
|
||||
_ (run-cli ["graph" "create" "--repo" export-graph] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "page" "--page" "ExportPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "block" "--target-page-name" "ExportPage" "--content" "Export content"] data-dir cfg-path)
|
||||
export-result (run-cli ["--repo" export-graph
|
||||
"graph" "export"
|
||||
"--type" "edn"
|
||||
"--output" export-path] data-dir cfg-path)
|
||||
export-payload (parse-json-output export-result)
|
||||
_ (run-cli ["--repo" import-graph
|
||||
"graph" "import"
|
||||
"--type" "edn"
|
||||
"--input" export-path] data-dir cfg-path)
|
||||
list-result (run-cli ["--repo" import-graph "list" "page"] data-dir cfg-path)
|
||||
list-payload (parse-json-output list-result)
|
||||
stop-export (run-cli ["server" "stop" "--repo" export-graph] data-dir cfg-path)
|
||||
stop-import (run-cli ["server" "stop" "--repo" import-graph] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code export-result)))
|
||||
(is (= "ok" (:status export-payload)))
|
||||
(is (fs/existsSync export-path))
|
||||
(is (pos? (.-size (fs/statSync export-path))))
|
||||
(is (= "ok" (:status list-payload)))
|
||||
(is (some (fn [item]
|
||||
(= "ExportPage" (or (:title item) (:block/title item))))
|
||||
(get-in list-payload [:data :items])))
|
||||
(is (= 0 (:exit-code stop-export)))
|
||||
(is (= 0 (:exit-code stop-import)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-export-edn")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
export-graph "export-edn-graph"
|
||||
import-graph "import-edn-graph"
|
||||
export-path (node-path/join (node-helper/create-tmp-dir "exports") "graph.edn")
|
||||
_ (run-cli ["graph" "create" "--repo" export-graph] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "page" "--page" "ExportPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "block" "--target-page-name" "ExportPage" "--content" "Export content"] data-dir cfg-path)
|
||||
export-result (run-cli ["--repo" export-graph
|
||||
"graph" "export"
|
||||
"--type" "edn"
|
||||
"--output" export-path] data-dir cfg-path)
|
||||
export-payload (parse-json-output export-result)
|
||||
_ (run-cli ["--repo" import-graph
|
||||
"graph" "import"
|
||||
"--type" "edn"
|
||||
"--input" export-path] data-dir cfg-path)
|
||||
list-result (run-cli ["--repo" import-graph "list" "page"] data-dir cfg-path)
|
||||
list-payload (parse-json-output list-result)
|
||||
stop-export (run-cli ["server" "stop" "--repo" export-graph] data-dir cfg-path)
|
||||
stop-import (run-cli ["server" "stop" "--repo" import-graph] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code export-result)))
|
||||
(is (= "ok" (:status export-payload)))
|
||||
(is (fs/existsSync export-path))
|
||||
(is (pos? (.-size (fs/statSync export-path))))
|
||||
(is (= "ok" (:status list-payload)))
|
||||
(is (some (fn [item]
|
||||
(= "ExportPage" (or (:title item) (:block/title item))))
|
||||
(get-in list-payload [:data :items])))
|
||||
(is (= 0 (:exit-code stop-export)))
|
||||
(is (= 0 (:exit-code stop-import)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-cli-graph-export-import-sqlite
|
||||
(async done
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-export-sqlite")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
export-graph "export-sqlite-graph"
|
||||
import-graph "import-sqlite-graph"
|
||||
export-path (node-path/join (node-helper/create-tmp-dir "exports") "graph.sqlite")
|
||||
_ (run-cli ["graph" "create" "--repo" export-graph] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "page" "--page" "SQLiteExportPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "block" "--target-page-name" "SQLiteExportPage" "--content" "SQLite export content"] data-dir cfg-path)
|
||||
export-result (run-cli ["--repo" export-graph
|
||||
"graph" "export"
|
||||
"--type" "sqlite"
|
||||
"--output" export-path] data-dir cfg-path)
|
||||
export-payload (parse-json-output export-result)
|
||||
_ (run-cli ["--repo" import-graph
|
||||
"graph" "import"
|
||||
"--type" "sqlite"
|
||||
"--input" export-path] data-dir cfg-path)
|
||||
list-result (run-cli ["--repo" import-graph "list" "page"] data-dir cfg-path)
|
||||
list-payload (parse-json-output list-result)
|
||||
stop-export (run-cli ["server" "stop" "--repo" export-graph] data-dir cfg-path)
|
||||
stop-import (run-cli ["server" "stop" "--repo" import-graph] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code export-result)))
|
||||
(is (= "ok" (:status export-payload)))
|
||||
(is (fs/existsSync export-path))
|
||||
(is (pos? (.-size (fs/statSync export-path))))
|
||||
(is (= "ok" (:status list-payload)))
|
||||
(is (some (fn [item]
|
||||
(= "SQLiteExportPage" (or (:title item) (:block/title item))))
|
||||
(get-in list-payload [:data :items])))
|
||||
(is (= 0 (:exit-code stop-export)))
|
||||
(is (= 0 (:exit-code stop-import)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [data-dir (node-helper/create-tmp-dir "db-worker-export-sqlite")]
|
||||
(-> (p/let [cfg-path (node-path/join (node-helper/create-tmp-dir "cli") "cli.edn")
|
||||
_ (fs/writeFileSync cfg-path "{:output-format :json}")
|
||||
export-graph "export-sqlite-graph"
|
||||
import-graph "import-sqlite-graph"
|
||||
export-path (node-path/join (node-helper/create-tmp-dir "exports") "graph.sqlite")
|
||||
_ (run-cli ["graph" "create" "--repo" export-graph] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "page" "--page" "SQLiteExportPage"] data-dir cfg-path)
|
||||
_ (run-cli ["--repo" export-graph "add" "block" "--target-page-name" "SQLiteExportPage" "--content" "SQLite export content"] data-dir cfg-path)
|
||||
export-result (run-cli ["--repo" export-graph
|
||||
"graph" "export"
|
||||
"--type" "sqlite"
|
||||
"--output" export-path] data-dir cfg-path)
|
||||
export-payload (parse-json-output export-result)
|
||||
_ (run-cli ["--repo" import-graph
|
||||
"graph" "import"
|
||||
"--type" "sqlite"
|
||||
"--input" export-path] data-dir cfg-path)
|
||||
list-result (run-cli ["--repo" import-graph "list" "page"] data-dir cfg-path)
|
||||
list-payload (parse-json-output list-result)
|
||||
stop-export (run-cli ["server" "stop" "--repo" export-graph] data-dir cfg-path)
|
||||
stop-import (run-cli ["server" "stop" "--repo" import-graph] data-dir cfg-path)]
|
||||
(is (= 0 (:exit-code export-result)))
|
||||
(is (= "ok" (:status export-payload)))
|
||||
(is (fs/existsSync export-path))
|
||||
(is (pos? (.-size (fs/statSync export-path))))
|
||||
(is (= "ok" (:status list-payload)))
|
||||
(is (some (fn [item]
|
||||
(= "SQLiteExportPage" (or (:title item) (:block/title item))))
|
||||
(get-in list-payload [:data :items])))
|
||||
(is (= 0 (:exit-code stop-export)))
|
||||
(is (= 0 (:exit-code stop-import)))
|
||||
(done))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
(.chdir js/process "/")
|
||||
(spawn-server! {:repo "logseq_db_spawn_test"
|
||||
:data-dir "/tmp/logseq-db-worker"})
|
||||
(is (= "node" (:cmd @captured)))
|
||||
(is (= (node-path/join js/__dirname "db-worker-node.js")
|
||||
(first (:args @captured))))
|
||||
(is (= (node-path/join js/__dirname "../dist/db-worker-node.js")
|
||||
(:cmd @captured)))
|
||||
(is (some #{"--repo"} (:args @captured)))
|
||||
(is (some #{"--data-dir"} (:args @captured)))
|
||||
(is (not-any? #{"--host" "--port"} (:args @captured)))
|
||||
|
||||
Reference in New Issue
Block a user