bikeshaving / crank

The Just JavaScript Framework
https://crank.js.org
MIT License
2.69k stars 76 forks source link

Full-stack (meta?) framework / CLI #251

Open brainkim opened 1 year ago

brainkim commented 1 year ago

The Crank.js documentation website is being built with some hacked-together code which uses ts-node, nodemon, ESBuild’s JavaScript API, a funny little router, etc. It would be nice to package this behind a CLI.

I have been putting this off for a long time because of open questions of API design, not wanting to reinvent the wheel, and the fact that bundling/transpilation continue to evolve... but perhaps it is time, especially as I rewrite the docs to handle stuff like Vite / etc. I think it is possible to do it now, especially with ESBuild. Maybe we could even put the CLI directly in the Crank package. (probably not a good idea)

Naming ideas:

The parts of the framework so far:

Attack plan:

Development should be oriented around commands:

The meta-framework will likely need to provide server-side components like the following:

TODO: Write hypothetical Getting Started docs.

brainkim commented 1 year ago

I have settled on the name shovel. For now. I’ve got ESBuild and node vm’s working. The develop command is useable, now I need to do static and maybe call it a day, though I’ve thought about also implementing server-side hot reloading.

I am progressing faster than I usually would, in no small part to ChatGPT.

https://github.com/bikeshaving/shovel https://github.com/bikeshaving/crank/pull/255

brainkim commented 1 year ago

Thinking about possible entry file exports for the static command.

Currently, I have:

export default {
  async staticPaths() {
    return [...paths];
  },
};

but I need to run additional code after paths have been turned into URLs and fetched.

Toying with some API ideas.

export default {
  async *static(dist) {
    for (const path of paths) {
      // TODO: Is there a useful yield value? The Response object? The absolute path?
      yield path;
    }
    await Storage.write("dist", );
  },
};
export default {
  async *static() {
    yield *paths; 
    await Storage.write("dist");
  },
};

The problem with naming it static, is that it’s a pseudo-keyword that will probably confuse people. So maybe just keep the same name (staticPaths) and make it polymorphic to accept async generators?

Also I don’t want to create an association that CLI commands and root default exports should have the same name. For instance, shovel develop calls the fetch() function.

export default {
  async fetch(req) {
    /* ... */
  },
  // I also like the idea of passing in the destination directory.
  async *staticPaths(outDir) {
    yield *paths;
    await Storage.write(outDir);
  },
};

Not bad...

More thoughts.

Am I still down with defining this all on the default export? Yes, I guess, in the sense that the default fetch method aligns with the way Cloudflare Workers/bun does it.

Okay I have a plan, and it won’t be a breaking change!