polylith icon indicating copy to clipboard operation
polylith copied to clipboard

Add ClojureScript support

Open furkan3ayraktar opened this issue 11 months ago • 3 comments

This PR adds ClojureScript support to the poly tool. There is a longer discussion explaining the rationale behind here.

Some of the decisions to keep the scope of the changes small without compromising the overall value:

  • All components, bases, and projects live under a single Polylith monorepo regardless of the dialects used within them.
  • The components and bases can mix clj, cljs, and cljc files in their source files.
  • The workspace.edn will have a new config option called :dialects to let users restrict dialects in their workspace.
  • The poly tool will also read cljs files, in addition to the cljc and clj files, if cljs is enabled in the current workspace.
  • A component or base with a modified file will be marked as changed regardless of the dialect. As a result, all dependent components will be marked as indirectly changed.
  • We decided to leave testing out of scope and rely on shadow-cljs or similar for testing.
  • The Polylith team will provide a simple development setup for a mixed (or ClojureScript only) workspace using shadow-cljs. The users can choose their own way to create a classpath and start their own clj/cljs REPLs.

TODOs:

  • [x] Add dialects to workspace config
    • The :dialects config option works as follows. The user can define a set of dialects. Valid dialects are: "clj" and "cljs". If the dialects option is not defined or if it's an empty set, it will be treated as if it is #{"clj"}. This is necessary for backward compatibility. If it is #{"clj", "cljs}, .clj, .cljs, and .cljc files will be considered as valid code sources.
  • [x] Handle require-macros case
    • ClojureScript files can require macros from clj files using :require-macros.
  • [x] Ensure the default test runner works without breaking
    • The external test runner will need an update for ClojureScript-enabled workspaces.
  • [ ] Handle NPM dependencies in the libs command
    • Read the package.json files and include those dependencies in the libs command.
    • Each brick and project should have a package.json if they use NPM dependencies.
  • [ ] Update the create command to support creating ClojureScript bricks and projects.
  • [x] Add an example project under examples with corner cases.
    • Project should contain:
      • A component with only clj sources
      • A component with clj and cljc sources
      • A component with clj, cljs, and cljc sources
      • A component with only cljs sources
      • A component with a cljs source and an accompanying clj source with macro definitions. The cljs file should require a clj file using require-macros. There should be additional clj files that the main clj file that contains the macros should require regularly.
  • [ ] Create a sample development environment & projects with shadow-cljs
  • [x] Update the documentation
    • Explain :dialects key
    • Explain how to work with ClojureScript (new section)
  • [ ] Update the FAQ for ClojureScript support (gitbook)

furkan3ayraktar avatar Dec 26 '24 14:12 furkan3ayraktar

When you get around to this:

Update the create command to support creating ClojureScript bricks and projects.

I recommend adding new templates under creator/templates/<dialect>/ but otherwise matching the structure of the default templates.

The search order can then be:

  • per-project, per-dialect template, else fall back to
  • per-user, per-dialect template, else fall back to
  • default (internal), per-dialect template, else fall back to
  • per-user template, else fall back to
  • per-project template, else fall back to
  • default (internal) template (else error)

It would be simpler to do the per-dialect to default fall back on a per-tier basis but that could cause a user's (Clojure) template to take precedence over the default ClojureScript one, which is not what we want.

This ensures the new template machinery is purely additive and will not break anyone's existing templates, and it would also allow for templates/clj/ to have Clojure-specific be different from the default if users want that.

seancorfield avatar Dec 28 '24 19:12 seancorfield

An additional thought: when the dialect is plumbed into the creator component, it would be a good idea to add :dialect dialect to the data passed into the template renderer, so that templates can contain conditional logic to produce different output for clj/cljs if users want:

{% ifequal dialect "cljs" %}
... some cljs-specific code ...
{% else %}
... some clj-specific code ...
{% endifequal %}

seancorfield avatar Dec 29 '24 19:12 seancorfield

@tengstrand I added a couple of notes to your latest commit: there are a couple more places that need dialect passed into templates.

The new templates.adoc file will also need updating to note that {{dialect}} is a new variable in all the templates.

seancorfield avatar Dec 30 '24 22:12 seancorfield