Skip to content

Allow adapters to have their own dependencies #82

@strogonoff

Description

@strogonoff

This would allow things like removing jsdom from core, and having adapters for e.g. Markdown that use some preexisting Markdown parsers.

Currently, adapters specified in anafero-config.json are built on the fly from TypeScript source, and no custom dependencies are allowed. This makes it easy to inspect and review the code.

Option 1: custom dependency mechanism

To support custom dependencies with current approach we would need to fetch them based on, say, package.json, and make them available to esbuild. Resolution could involve substantial amount of logic and we would never support all possible ways of specifying dependencies in say package.json.

Option 2: pre-built adapters

Alternatively, we could support a pre-built adapter bundle, where TS is pre-compiled and everything is bundled into one JS file.

If we want to review adapters for safety, it is possible with pre-built adapters:

  • Create a hash/checksum of pre-built adapter contents (bundle & supporting assets) provided by adapter author
  • Build adapter from scratch and create a hash/checksum of that
  • Fail if checksums don’t match
  • Manually review adapter’s original TypeScript source & vet dependencies

The last step would be a simple review, as with plain TS adapters, just with added dependency vetting.

Building an adapter should be possible using an anafero CLI subcommand.

Downsides:

Option 3: resolve URL imports at runtime

Make it possible for adapters to do import 'https://example.com/somemodule@1.2.3' and fetch this at runtime. Actually, this is partly implemented already.

It’s compelling, but there are downsides:

  • Relying on third-party infrastructure is dangerous, running own infrastructure is expensive

    • If example.com from the above example goes down, running extensions will become impossible
      • Would break further website builds (adapters are executed at build time, to extract resources & format content)
      • Would degrade website read experience (adapters contribute dynamic features to content)
      • Would make online editing impossible (adapters are required to edit content)
    • If example.com becomes malicious, it’s worse because it can serve bad code
  • Adapter needs to specify import URL that ties it to particular infrastructure

  • Hard or impossible to verify (things that get served from third-party infrastructure can change)

  • Slower generation times, especially if an adapter has a large dependency tree

Alleviaton:

  • link() function at Node build time can enforce constraints on URL imports
    • We can limit URL imports to specific whitelisted or first-party domain names
    • We can require pinned URLs
    • We can do it depending on environment (e.g., dev/production)
  • To avoid changes and degradation at runtime, at build time we can make all files fetched when resolving URL imports to be part of generated site (under some prefix). A simple rewrite of imports in generated adapter code should be enough.
    • Caveat: rewrite is simple for absolute URLs, but domain-relative URLs would need to also be detected and augmented with path prefix (if we simply output those files following the source’s URL scheme, it can clash with generated site).

Option 4: require vendoring

Technically, this is always possible to do by hand. Without some automation, extremely cumbersome for an extension with a large dependency tree.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions