TypeScript icon, indicating that this package has built-in type declarations

    2.22.1 • Public • Published

    Todo Package

    Provides a mechanism for building a todo and all of its related structures given a todo id. The resulting data structures hold a variety of information that can be used for managing the todo in a UI or to make any updates to the system

    Important concepts

    For the sake of simplifying naming in this library, every reference to a Todo is actually intended to represent a TodoAssignment. So when passing the "todo id" to the "todo loader", really a todo assignment id should be passed.

    Publishing to npm

    This repo is manually published to npm using Semantic Versioning guidelines.

    For example: major.minor.patch Incrementing +0.0.1 would be a bug. +0.1.0 would be a minor upgrade, +1.0.0 would be major upgrade

    1. First update the version in the package.json
    2. Then, update your local main branch
    3. Run npm publish

    Installation / setup

    In order to load a todo with all of its information, it's necessary to have access to a TodoLoader. This can either be loaded as a standalone class or built out of the NestJS dependency injection container.

    yarn add @endpoint/todo


    When using the TodoLoader outside of a NestJS project, the TodoLoader instance can be built from the TodoLoaderFactory:

    import { TodoLoaderFactory } from '@endpoint/todo';
    const apolloClient: ApolloClient<object> = useApolloClient(); // in a react app
    const todoLoader = TodoLoaderFactory.build(apolloClient);


    The Todo

    The Todo structure represents a todo as it currently exists in the system. It contains various top-level information and a pointer to the current TodoStep.

    Loading a todo

    A Todo structure can be built by passing a todo's id to the load method of the TodoLoader.

    yarn add @endpoint/todo

    import { Todo, TodoLoader } from '@endpoint/todo';
    const todoLoader = TodoLoaderFactory.build(apolloClient);
    const todo: Todo = await todoLoader.load('some-todo-assignment-id');

    Traversing the steps of a todo

    Current step

    It is frequently necessary to determine which step a user should currently be working on in a todo. For this you can use the currentStep property:

    import { TodoStep } from '@endpoint/todo';
    const step: TodoStep = todo.currentStep;
    Moving to the next step

    At any point a user may wish to move on to the next step. This may be after they've completed the current step, or if they choose to skip to the next section of the todo.

    if (todo.canMoveToNextStep()) {
      todo.currentStep; //is now the next step

    The behavior of moveToNextStep() is determined by the configuration of the todo sections and the completion status of the current step. If a user has not completed the current step, an attempt will be made to move the user on to the subsequent section, skipping over the remaining uncompleted steps of the current section. If a user has completed the current step, moving to the next step will either bring up the next uncompleted step in the current section or move the user on to the next section if there are no remaining steps in the current section.

    Going back to the previous step

    The previous step is defined as the last step that a user saw.

    if (todo.canMoveToPreviousStep()) {
      todo.currentStep; //is now the previous step
    Moving back to a specific step

    If a user wishes to edit their answer to a step, it's possible to change the currentStep pointer to a specific step:

    if (todo.canMoveToStep(step)) {
    Listening for changes to the current step

    If it's necessary to listen for when the current step changes, a listener can be attached to the todo's step.change event.

    todo.on('step.change', (newCurrentStep) => {
      //render new step
    Checking if a todo has finished all steps

    At any point it may be useful to check if a todo has any more steps to complete:

    if (todo.hasFinishedAllSteps()) {
      //enable the "submit" button on the confirmation page

    The TodoStep

    A TodoStep is the atomic unit of action that a user must complete as defined by the TodoStepPrimitive. A collection of these represent a linear pathway through a todo section.

    The TodoStepPrimitive

    The TodoStepPrimitive is a representation of the primitive type of the step. This can be anything from a simple acknowledgement to a flow for gathering financial information.

    import { TodoStepPrimitive } from '@endpoint/todo';
    const primitive: TodoStepPrimitive = todo.currentStep.primitive;
    primitive.name; //ex: acknowledgement
    primitive.options; //unique to each primitive

    Answering a step

    When a todo step primitive's corresponding UI component receives an answer from the user, it can call the setAnswer method on the TodoStep:

    try {
      step.setAnswer({ foo: true });
    } catch (error) {
      //the answer schema is invalid

    Once a valid answer is provided, it's possible to move on to the next step:

    if (todo.canMoveToNextStep()) {
      todo.currentStep; //is now the next step

    It's also possible to get the value of a step's answer using the answer property:

    step.answer; //schema is unique to each primitive

    Removing an answer

    It might be necessary to change a step's answer. This can be done by calling the unsetAnswer method on the step:



    Each TodoStep has information about the expected layout of the step as it should be presented to the user. These are defined for each todo in their configuration files. The layout of a step can be accessed from the layout property:

    import { TodoStepLayout } from '@endpoint/todo';
    const layout: TodoStepLayout = todo.currentStep.layout;

    A layout is built out of a sequence of blocks, which are provided in the order that they are expected to be shown. Each block has a name that describes how it should be laid out in a UI and the options that were provided to build it:

    for (const block of layout.blocks) {
      block.name; //ex: title
      block.options; //ex: {value: "The todo's title"}

    Working with data points

    Todos are frequently used to gather data from a user. Each todo configuration has the ability to specify a dataKey which marks it as a piece of data that should be lifted to the surface level of the todo. These data points might be what you use to present a todo "summary/confirmation" page to the user after completing all the steps.

    The Todo has a method getDataPointSteps() that can be called to iterate over the known data points. Until a todo section's pathway has been traversed by the user, the only data points that will be available are the ones before any uncompleted branching points.

    import { TodoStep } from '@endpoint/todo';
    const dataPointSteps: TodoStep[] = todo.getDataPointSteps();

    Synchronizing with the API

    This library will always try to send unsaved data to the API for storage. It also periodically checks for updates that were made on other devices.

    When new data has been loaded into the todo from an external source, an event is dispatched:

    todo.on('update', () => {});

    Local development with Everest client

    yarn link

    For local development, there are often times you want to test out new feature or when trying to debug an issue with this library in Everest client (all without publishing the package). To do so, you can follow these steps:

    In @endpoint/todo:

    • Make changes locally
    • Run yarn build
    • Run yarn link

    In Everest client:

    • Run yarn link @endpoint/todo
    • Restart your local server
    • Profit


    Depending on your use case, a faster alternative is to make changes directly in the node_modules/@endpoint/todo/ directory of Everest client. You'll also retain hot module reloading.




    npm i @endpoint/todo

    DownloadsWeekly Downloads






    Unpacked Size

    798 kB

    Total Files


    Last publish


    • vbeutner-endpoint
    • eschroeder-endponint
    • aescalante-endpoint
    • asobh-endpoint
    • jrocha-endpoint
    • endpoint-cjamison
    • nlucking-endpoint
    • dvillada-endpoint
    • fnavia-endpoint
    • rbhatia-endpoint
    • eeruguz-endpoint
    • cchaplin1
    • endpoint-rovrevik
    • tocchipinti-endpoint
    • melafifi-endpoint
    • rdiaz-endpoint
    • cgallego
    • sandeep-endpoint
    • endpoint-zkhan
    • endpoint-gbirlan
    • endpoint-rellis
    • miry2j71
    • endpoint-vtsang
    • rhinojosa
    • jaywang-endpoint
    • ccarmona2
    • stevepark_endpoint
    • sreed-endpoint
    • avo-endpoint
    • cperezep
    • julio_rpadev
    • wtiu-endpoint
    • rlong-endpoint
    • ivansaldarriaga
    • dsalehi-endpoint
    • jguillen-endpoint
    • karolinahidalgo
    • coh-endpoint
    • dsteinbach-endpoint
    • angelaho-ep
    • jcamaraendpoint
    • slavashkliaryk
    • rpelikh-endpoint
    • gvaldez-endpoint
    • acutler-endpoint
    • jrede
    • mario-rodz
    • hvargas
    • ttorres
    • areizaendpointclosing
    • hropa
    • sanjay_endpoint
    • franktiquepoint
    • jacobhaile
    • apark
    • jingalls777
    • savery-endpoint
    • aalcarazz
    • hangtuendpoint
    • viocost
    • melarabi
    • ahenderson_endpoint
    • john_brown
    • spachunuri
    • walt_zimmerman
    • sellerendpoint
    • raymondwang147
    • jdriscoll
    • nolson-fams
    • binhxn
    • nthurnau_endpoint
    • aodevelopment
    • davidbanthony
    • endpointengineering
    • sean.donnelly
    • janhartigan
    • gtournie
    • munsellj
    • drewpm
    • graysongladstone
    • joey.endpoint
    • endpointbob
    • realdeprez-ep
    • shenyusun
    • olga-gushchyna
    • david-endpoint
    • markgx
    • gil_roman
    • jrossendpoint
    • tuhin-sah
    • babakontheweb
    • nfisher-endpoint
    • asrivastava
    • ipintado
    • mlancaster-endpointclosing
    • ericvandevprod
    • ryanendpoint
    • jmanahan
    • dzhmurchuk
    • vryneiski
    • anepyivoda
    • anna_palashevska
    • vlad_varnava
    • jzhizhenka
    • wangmta
    • skucab
    • icacho
    • ybukhtaendpoint
    • nhryshchankova
    • ksinyachevskiy
    • esalino
    • sean-beard-endpoint
    • johnson973
    • juannavarrete
    • ksubsara
    • shaneatendpoint
    • dnegrete-ep
    • eloria
    • wmarroquin