stackblitz / tutorialkit

TutorialKit by StackBlitz - Create interactive tutorials powered by the WebContainer API
https://tutorialkit.dev
MIT License
513 stars 49 forks source link

A command that I can run for a specific lession/chapter without restarting the running command #257

Open noam-honig opened 3 months ago

noam-honig commented 3 months ago

Is your feature request related to a problem?

Sometimes, between steps in my tutorial, I want to do some cleanup or similar operations, and would like to run a command.

Describe the solution you'd like.

Currently there are only prepare command, and main command - I don't want to restart the running main command, I just want to run a command when the lesson / chapter starts (in my case, delete the ./db/tasks.json file.

Describe alternatives you've considered.

I injected javascript to files the user doesn't see at this stage - it's an ah... solution

Additional context

No response

Nemikolh commented 3 months ago

Oh that's an interesting use case! It does make sense to want to do some cleanup between lessons.

Like maybe have a cleanupCommand property that always gets executed when moving from one lesson to another. The tricky bit will be to know when to synchronize it with the other commands. I'm not sure if it would work well in every usecase.

Have you considered creating a custom component for this?

I think the following should work well:

import { useEffect } from 'react';
import { webcontainer } from 'tutorialkit:core';

export const MyComponent = ({}) => {
  useEffect(() => {
    (async () => {
      const webcontainerInstance = await webcontainer;

      webcontainerInstance.fs.rm('/db/tasks.json', { force: true });
    })();
  }, []);

  return null;
};

Then in a content.mdx lesson:

---
type: lesson
---

import { MyComponent } from '@components/MyComponent';

<MyComponent client:load />

(I just noticed that the type of webcontainer is incorrect and should be Promise<WebContainer>)

noam-honig commented 3 months ago

I wasn't aware of this option or the api of webcontainer from tutorialkit:core This looks cool

I did it in a javascript file that I run in a template

https://github.com/remult/remult/blob/main/docs/interactive/src/templates/before-entity/backend/index.ts

Nemikolh commented 3 months ago

That works too! So your backend is always restarted between lessons?

noam-honig commented 3 months ago

That works too! So your backend is always restarted between lessons?

I'm using vite to also hotreload my backend: https://github.com/remult/remult/blob/main/docs/interactive/src/templates/default/vite.config.ts

Nemikolh commented 3 months ago

Wow I had no idea you could do that with vite! This is a really nice trick! :star_struck:

Thanks for sharing :heart:

Are you happy with your current solution then? Or do you think a custom option in TutorialKit would still be needed?

noam-honig commented 3 months ago

@Nemikolh I'm inclined to having a lesson-setup command - I think it's easier to grasp, but as for my code - I can live with what I've done or with the solution you offerred

Nemikolh commented 3 months ago

Don't you mean more like a cleanup that runs only after moving away from a lesson?

Or would you expect that command to be executed on the first lesson a user navigates to, before the prepareCommands?

noam-honig commented 3 months ago

In my use case, I needed it before a lesson starts. In my tutorial - the first page is a welcome page that shows the app we're going to write, and then we start writing it. The first page has data in the "db/tasks.json" file - once I move to the second lesson - I want to delete that data so the user will insert it themselves.

Nemikolh commented 3 months ago

Ah interesting! I suppose we could expose several "hooks" commands that execute at specific time of the lifecycle of a tutorial. That way it would work for a larger variety of usecase.

It would be interesting to get more data before we start working on this though. Let's keep this issue open and see if others would be in need of a similar solution and what they would want.

This can definitely be done post-1.0.