Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Deno with plugins #28126

Open
CyanChanges opened this issue Feb 15, 2025 · 4 comments
Open

Extend Deno with plugins #28126

CyanChanges opened this issue Feb 15, 2025 · 4 comments

Comments

@CyanChanges
Copy link
Contributor

CyanChanges commented Feb 15, 2025

A way to extend Deno with plugins.

Like Bun Plugins

Deno plugins is able to modify the import(require) logic, like:

  • Handle import module load (for example, matching /\.(yaml|yml)$/ to implement a custom yaml file loader)
  • Handle import resolutions
  • Register virtual modules (like register #db and export database connection)
  • Purge Module Cache (allowing customized hmr)

deno plugins might be under a permission flag to prevent abuse.

Example Use cases

interface ResolvedModule {
  href: URL, // module url, like `npm:zod`, `file:///home/user/loader/tree.ts`
}

interface Module {
  exports: any, // module exports
  type: "module" | "commonjs" // module type
}

interface OnLoadOptions {
  specifier: string, // import specifier, like "`./tree.ts`"
  attributes: object, // import attributes, like `{ with: { type: "yaml" }}`
  origin: URL, // which module tries import this like `file:///home/user/loader/mod.ts`
  next(resolved: ResolvedModule): Promise<Module> // 
}

For example, implementing YAML loader:

// function
Deno.plugin(async (loader) => {
    const { load } = await import("js-yaml");

    loader.onLoad({ match: /\.(yaml|yml)$/ }, async (path, _options: OnLoadOptions) {
      return {
        exports: load(await Deno.readTextFile(path)),
        type: "module"
      }
    })
})

// object 
Deno.plugin({
  name: 'yaml-loader'
  async setup(loader) {
    const { load } = await import("js-yaml");

    loader.onLoad({ match: /\.(yaml|yml)$/ }, async (module: ResolvedModule, _options: OnLoadOptions) {
      const { path } = module
      return {
        exports: load(await Deno.readTextFile(path)),
        type: "module"
      }
    })
  }
})

And virtual module (override could existing module):

Deno.plugin(async (loader) => {
  const db = drizzle(...)
  const mod = await loader.module('#db', (attributes: object, next: (attributes: object) => Promise<Module>) => { // next for default resolution
    return {
      exports: db,
      type: "module"
    }
  })
})
@petamoriken
Copy link
Contributor

petamoriken commented Feb 16, 2025

Since these proposals involve violations of the current ES spec (as I pointed out on Discord), I believe the correct route is to make a standardization request to TC39, not to Deno.


  • Handle import module load (for example, matching /\.(yaml|yml)$/ to implement a custom yaml file loader)
  • Handle import resolutions
  • Register virtual modules (like register #db and export database connection)

Related to Stage 1 Compartments proposal. It would be good to provide feedback there.

  • Purge Module Cache (allowing customized hmr)

You know, currently it is not allowed to access the ESM cache on the hosts (browser runtimes, Node.js, Deno, Bun and so on). As far as I know, it is not even proposed in TC39, so it is better to offer it on TC39 Discourse or Matrix chat room. Please check the ECMA262 CONTRIBUTING.md for more information.

@petamoriken
Copy link
Contributor

related: #27820

@CyanChanges
Copy link
Contributor Author

Since these proposals involve violations of the current ES spec (as I pointed out on Discord), I believe the correct route is to make a standardization request to TC39, not to Deno.

  • Handle import module load (for example, matching /\.(yaml|yml)$/ to implement a custom yaml file loader)
  • Handle import resolutions
  • Register virtual modules (like register #db and export database connection)

Related to Stage 1 Compartments proposal. It would be good to provide feedback there.

  • Purge Module Cache (allowing customized hmr)

You know, currently it is not allowed to access the ESM cache on the hosts (browser runtimes, Node.js, Deno, Bun and so on). As far as I know, it is not even proposed in TC39, so it is better to offer it on TC39 Discourse or Matrix chat room. Please check the ECMA262 CONTRIBUTING.md for more information.

Node provide internals which allow me to access the cache.
Bun also have require.cache.
Although they aren't allowed, but it is possible to access if you really want.

It took months for a new proposal, and even more time for it to be implemented.

Anyways, I will try propose on TC39.

@CyanChanges
Copy link
Contributor Author

Also, you can handle module load in Node.js with Module.register.
the same thing possible in Bun with plugins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants