Updating the prisma schema

cd packages/engine-server
make db-gen

Note Response

  • NOTE: response has been truncated in some areas with ... for sake of clarity
    "id": "e3002a40-6571-4120-8311-c4a9af948e07",
    "title": "Foo",
    "vault": {
        "fsPath": "/Users/kevinlin/Dropbox/Apps/Noah/vaults/people-vault"
    "type": "note",
    "desc": "",
    "links": [
            "type": "wiki",
            "from": {
                "fname": "foo",
                "id": "e3002a40-6571-4120-8311-c4a9af948e07"
            "original": "people.james",
            "value": "people.james",
            "alias": "people.james",
            "pos": {
                "start": 128,
                "end": 155
            "to": {
                "fname": "people.james"
    "fname": "foo",
    "updated": 1610409926314,
    "created": 1610381470060,
    "parent": "af9c2275-84dd-4d86-b0a3-af9d8cd2fb08",
    "children": [],
    "body": "...",
    "data": {},
    "custom": {
        "published": true

Adding a new engine API

Engine apis have many touchpoints.

See Initialization to see the different components that an engine call (in this case, initialization), calls.

When you add a new API to the engine, it needs to be added in both the types and the implementations of the engine:

  • types:

  • implementation:

    • Store: engine methods usually operate on the storage layer (eg. write to disk, read from disk) and so store methods often need to be updated
    • Engine: actual engine implementation
    • DendronApi: used by engine client to call the express server
    • API Server Routes: where the server handles the call from engine client
    • DendronEngineClient: Implements the call from engine client to API
    • DEngineClient: wrapper around DendronAPI that mirrors the Engine API

Tune Search Results

  1. checkout fuse.js from

  2. install dependencies

    npm install
  3. build the docs

    npm run docs:dev
  4. modify docs/.vuepress/components/Demo/Demo.vue

    • example of setting custom parameters
    let codify = (pattern) => {
    return `const options = {
        shouldSort: true,
        threshold: 0.6,
        location: 0,
        distance: 50,
        maxPatternLength: 32,
        minMatchCharLength: 2,
        useExtendedSearch: true,
        includeScore: true,
    keys: [
    const fuse = new Fuse(list, options);
    // Change the pattern
    const pattern = "${pattern}"


#scope.common.lookup (Private)

Connecting to the engine

import { DEngineClientV2, EngineConnector } from "@dendronhq/engine-server";

let dendronEngine: DEngineClientV2;
const connector = EngineConnector.instance();
if (_.isUndefined(connector._engine)) {
    return vscode.window.showInformationMessage(
    "Still initializing. Please close this window and try again after Dendron has been initialized",
dendronEngine = connector.engine;
if (!engine) {
    engine = this.initMarkdownEngine({ sourceUri, dendronEngine });

Querying notes by ID


Query notes by file name

  • note: make sure that the engine is initialized

  • with vault

import {NoteUtilsV2} from "@dendronhq/engine-server";

const maybeNode = NoteUtilsV2.getNoteByFnameV4({
    fname: dirname,
    notes: nodes,
  • without vault (gets all notes with this name)
import {NoteUtilsV2} from "@dendronhq/engine-server";

const maybeNode = NoteUtilsV2.getNotesByFname({({
    fname: dirname,
    notes: nodes,


Getting absolute path for a vault

Dendron has many vault types (Private) which means that getting the path to the vault is not as simple as path.join(wsRoot, vault.fsPath). To get the path of the vault relative to wsRoot, use the following:

// Path of vault relative to workspace root
path.join(wsRoot, VaultUtils.getRelPath(vault))


#scope.common.markdown (Private)

Adding a new unified plugin



  • Dendron uses remark and rehype to handle markdown and html transformations
  • Dendron uses a series of processors to group unified plugins
  • Dendron currently compiles markdown into output formats listed here


  1. add the plugin to engine-server
    • NOTE: we are still using remark12 so make sure to install the remark12 compatible version of the plugin
    • instructions to add new packages here
  2. update src/markdown/utils.ts in engine-server
    • import plugin and add it to the appropriate processor (most likely procFull)
  3. write a test for the plugin. plugin tests are located in engine-test-utils/src/__tests__/engine-server/markdown/
    • example here
    • createProcTests is a special function that sets up a Dendron workspace and can help you run a unified processor for multiple output formats
    • your test should cover every output format that your plugin affects
    • best way to understand is by example, see the other tests in the same folder for additional examples of how to use this function
  4. write the plugin implementation
  5. make sure your tests pass
    • its helpful to use the matchSnapshot functionality that jest provides if you use the checkVFile helper function, this happens automatically
    • you can view snapshots in __snapshots__/ folder which is relative to the test
  6. add a flag in DendronConfig to toggle the plugin
    • by default, new plugins are opt-in
    • if the plugin only affects HTML output, you can put the option in DendronSiteConfig
  7. go back into src/markdown/utils.ts and use the newly created config value
    • pass it in as an optional param in proc*
    • conditionally add plugin in config is present
  8. add a test that makes sure the plugin doesn't take into affect if the config is not enabled

Notes on testing:

  • when testing transformers, process will run over the node that is passed in to the processor
  • when testing parsers and compilers, process will run over the text that you pass into it

  1. Upload New Prisma Client