diff --git a/Server-Client-level-API.md b/Server-Client-level-API.md new file mode 100644 index 0000000..2c9ddf2 --- /dev/null +++ b/Server-Client-level-API.md @@ -0,0 +1,131 @@ +This document outlines the high-level Server API exposed by sbt 1.0. Beneath this API is one of simple `Request`/`Response`/`Event` messages. While that API will expounded upon, this API represents the "core" of what the other API should expose, and the "best mechanism" of how to consume it. + + +# Connecting to sbt + +```scala +package sbt.client +/** + * This represents something that will connect to the sbt server *and* reconnect on failure. + * + * You can close the connection and stop reconnecting by calling `close()`. + */ +trait SbtConnector extends Closeable { + /** + * Register a callback to be notified on initial connection and subsequent reconnects to + * an sbt server. If the server is already connected, the handler will be called immediately. + * + * @param handler A callback that will be called upon every connection/reconnect. + * @param ex The context (thread) where the handler should be executed. + */ + def onConnect(handler: SbtClient => Unit)(implicit ex: ExecutionContext): Subscription +} +``` + +# Interacting with the Server + +```scala +package sbt.client +/** This represents a connection to the Sbt server, and all the actions that can be performed against an active sbt build. */ +trait SbtClient extends Closeable { + + /** + * This is our mechanism of watching the build structure to see when it changes, + * and update our information about the build. + * + * @param listener - A listener that is notified on build structure changes. + * @param ex - The context in which we should execute the listener. + * + * @return + * A subscription which can be used to unsubscribe to notifications. + * + * Note: This will load the entire build structure and pass it too us. + */ + def watchBuild(listener: BuildStructureListener)(implicit ex: ExecutionContext): Subscription + + // TODO - A mechanism to dynamically load key-dependencies, which are too expensive to compute up front. + // Possibly via watching a project and pulling configuration off of it. + + /** + * Gives us the autocompletions possible for a given command string. + * + * @param partialCommand An incomplete command or task string + * + * @return A set of "more complete" strings that could be used as sbt commands. + * + * TODO - This should probably return some more structured "completion" thing. + * That would allow us to return examples or types that a client would not use + * in autocomplete... + */ + def possibleAutocompletions(partialCommand: String): Future[Set[String]] + + /** + * This tries to find whether there is a build key associated with the + * current string. + * + * TODO - default/current project? + * TODO - How to handle delegate keys? + * TODO - Does this make sense to expose? + */ + def lookupScopedKey(name: String): Future[Option[ScopedKey]] + + /** + * Runs the command/task associated with the given input string. + * + * @param commandOrTask The full command/task string to run. + * that should be evaluated. + * @return A future that will return Unit if the command request was successfully sent. + */ + def requestExecution(commandOrTask: String): Future[Unit] + + /** + * Adds a listener to general events which are fired from this sbt server. These can be things like + * "TaskStarted, TaskCanceled, or even custom events from plugins (via GenericEvent). + * + * @param listener A function that is called when events are fired from sbt. + * @param ex The execution context on which to call the listener. + */ + def handleEvents(listener: EventListener)(implicit ex: ExecutionContext): Subscription + /** + * Adds a listener to a particular setting. If this setting changes, the event listener + * will be notified with the new value (and sent the initial value). + * + * @param key The setting to listen to changes on. + * @param listener A function that is called when the setting value changes. + * @param ex The execution context on which to call the listener. + */ + def watch[T](key: SettingKey[T])(listener: ValueListener[T])(implicit ex: ExecutionContext): Subscription + /** + * Adds a listener for the value of a particular task. If the evaluated task result changes, the event + * listener will be notified of the new value. + * + * Since tasks read their state from the filesystem, it is not guaranteed that an event will be fired upon change *unless* some + * task in the dependency of the specified one is run, requiring the value of the current task to be re-evaluated. + * + * @param key The task to listen to changes for. + * @param listener A function that is called when the setting value changes. + * @param ex The execution context on which to call the listener. + */ + def watch[T](key: TaskKey[T])(l: ValueListener[T])(implicit ex: ExecutionContext): Subscription +} +``` + +# Various helper classes + +Subscription +```scala +package sbt.client +trait Subscription { + def cancel(): Unit +} +``` +various aliases: +```scala +package sbt +package object client { + type BuildStructureListener = MinimalBuildStructure => Unit + type ValueListener[T] = (ScopedKey, TaskResult[T]) => Unit + type EventListener = Event => Unit +} +``` +