Lifecycle

Initialization

Summary

  • check if we are in a dendron workspace
    • workspace can be a code workspace (a .code-workspace file) or a native workspace (folder with dendron.yml)
  • depending on what sort of workspace we're in, Dendron will instantiate either a Dendron[Native|Code]Workspace
    • if multiple folders have dendron.yml, dendron will resolve to the first one found. logic here
  • start engine server (local server that does indexing)
    • the engine server is spawned in a separate process
    • NOTE: if in DEV mode (when launching plugin using vscode build task), we do not spawn a separate process
  • reload workspace (connect to the local server)
  • activate file watchers

Components

Steps

Dendron Workspace Created

An instance of DendronWorkspace is created near the beginning of activation. This is a singleton god object that exists as long as Dendron is running. The only requirement for initialization is the location of Dendron's workspace root. Example initilization below

new DendronCodeWorkspace({
  wsRoot: path.dirname(DendronExtension.workspaceFile().fsPath),
  logUri: context.logUri,
  assetUri,
});

Keep in mind that with Native Workspaces, the root of the VSCode workspace may not be the root of the Dendron workspace. If the dendron.yml file is located in a subdirectory of the root, then that directory is the root for Dendron. Use findWSRootInWorkspaceFolders to find the actual root.

Check for workspace

_activate {
    stateService := new StateService
    initializeSentry
    ws := DendronExtension.getOrCreate
    _setupCommands
    _setupLanguageFeatures

    extensionInstallStatus :=
    if extensionInstallStatus = INITIAL_INSTALL
        MetadataService.setInitialInstall

    // do this if we're in a dendron workspace
    if isDendronWorkspace {
        activator = new WorkspaceActivator
        activator.activate

        // do logic depending on if its native workspace vs code workspace
        ...

        setupTraits
        setupSegmentWithCacheFlush

        // see [[Migration|dendron://dendron.docs/pkg.dendron-engine.t.migration]]
        changes = runMigrationsIfNecessary

        if !changes {
            runConfigMigrationIfNecessary
        }

        Sentry.setUser
        wsService.initialize
        wsService.writeMeta

        // ---
        showInitProgress {
            port = startServerProcess
            updateEngineAPI(port)

            if !webUI {
                treeView = new NativeTreeView
                context.subscriptions.push treeView
            }
            ws.reloadWorkspace // 312
            // custom set context logic
            ...

            MetadataService.setDendronWorkspaceActivated
            _setupCommands
            AnalyticsUtils.identify

            if InstallStatus.INITIAL_INSTALL warnIncompatibleExtensions
            ws.activateWatchers // [[Lifecycle|dendron://dendron.docs/pkg.plugin-core.ref.watchers.arch.lifecycle]]
            togglePluginActiveContext

        }
    } else {
        autoInit = new FileAddWatcher
    }

    // initial install logic
    if InstallStatus.INITIAL_INSTALL {
        ...
    }

    showWelcomeOrWhatsNew

    if DendronExtension.isActive {
        HistoryService.instance().add(extension, activate)
        // If automaticallyShowPreview = true, display preview panel on start up
    }

}

Reload Workspace

  • src/commands/ReloadIndex.ts
// 49
reloadWorkspace {
    ws.reloadWorkspace
    if isFirstInstall {
        showTutorial
    }
    postReloadWorkspace
    emit(extension, initialized)
}

postReloadWorkspace

postReloadWorkspace {
    previousWsVersion = config.get(WORKSPACE_STATE.WS_VERSION)

    if previousWsVersion == 0.0.0 {
        execute(Upgrade)
        config.set(WORKSPACE_STATE.WS_VERSION, ws.version)
    } else {
        newVersion :=
        if (newVersion > previousWsVersion) {
            execute(Upgrade)
            config.set(WORKSPACE_STATE.WS_VERSION, ws.version)
            emit(extension, upgraded)
        }
    }

}

showWelcome

showWelcomeOrWhatsNew {
    switch(extensionInstallStatus) {
        case INITIAL_INSTALL {
            showWelcome
        }
        ....
    }
}

showWelcome {
    welcomeContent :=
    view = createWebviewPanel(welcomeContent)

    view.on(msg => {

        switch(msg {
            case initializeWorkspace {
                LaunchTutorialWorkspaceCommand.run
            }
        })

    })
}

Reference

getOrCreate

if !_DendronWorkspace
    _DendronWorkspace = new DendronWorkspace
constructor {
    @_setupCommands
    ...
}

activator.activate

if (NATIVE) {
  activateNativeWorkspace;
} else {
  activateCodeWorkspace;
}
activateCodeWorkspace {
    new DendronCodeWorkspace
}
class DendronCodeWorkspace extends DendronBaseWorkspace {
    constructor {
    }
}

startServerProcess

startServer {
    maybePort :=
    if !maybePort {
        launch()
    }
}

updateEngineAPI

  • src/utils.ts
WSUtils.updateEngineAPI {
    EngineAPIService.updateEngineAPI(
        vaults,
        wsRoot
    )
}
class EngineAPIService {
    create {
        const vaults =
            DendronWorkspace.instance().vaults?.map((ent) => ent.fsPath) || [];
        DendronEngineClient.create({ vaults, ws, port, history })
    }
}

workspace.vaults

get vaults {

}

ws.reloadWorkspace

executeCommand(RELOAD_INDEX);

setupLanguageFeatures

_setupLanguageFeatures {

    registerReferenceProvider;

    registerDefinitionProvider;

    registerHoverProvider;

    registerFoldingRangeProvider

}

Workspace Creation

This describes everything that happens after a user runs Initialize Workspace. See source code here.

Running a Command

When a command is executed, it runs the following functions in order. Source code here

  • sanityCheck: does basic checks
  • enrichInputs: cleans up passed in inputs
  • execute: runs the actual command
  • showResponse: show response to the user

Activate

  • activating dendron involves the following steps

    • dendron api server started
    • dendron engine finish indexing notes
  • extension, initialized: engine is loaded

  • other

    • extension, not_initialized: error with starting engine

Children
  1. Startup

Backlinks