Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Plugin packages #11

Open
aleclarson opened this issue Sep 6, 2022 · 2 comments
Open

Plugin packages #11

aleclarson opened this issue Sep 6, 2022 · 2 comments
Labels
enhancement New feature or request status: on hold Was in progress, but not currently

Comments

@aleclarson
Copy link
Contributor

  • Plugins found in node_modules are loaded automatically
  • Plugins can alter the generated client, which means they can:
    • Inject runtime code
    • Modify the db, pg, and t objects
    • Modify any TypeScript interface with declaration merging
  • Plugins can add their own config options to tusken.config.js
  • Plugins can alter the database schema with explicit permission
    • tusken apply brings up a multi-select prompt of unapplied plugins?
  • Plugins can add their own database schema for metadata purposes
@aleclarson aleclarson added the enhancement New feature or request label Sep 6, 2022
@aleclarson
Copy link
Contributor Author

aleclarson commented Sep 7, 2022

Database extensions

Any module in a plugin package's dist/database folder is read during tusken generate command. These modules are bundled and seamlessly plugged into the generated client. Private instance properties and global variables are renamed to avoid collisions between plugins.

import { Database, DatabaseConfig } from 'tusken'

const DEFAULT_FOO = 1

export default class extends Database {
  // Instance properties
  private _foo: number

  // Read and manipulate the config and/or initialize properties
  constructor(config: DatabaseConfig & { foo?: number }) {
    super(config)
    this._foo = config.foo ?? DEFAULT_FOO
  }

  // Define new methods
  foo() {...}
}

Similar runtime extensions will be supported as well. Like dist/select modules can extend the Select class. We might even allow plugin packages to provide their own extension namespaces, so dist/<plugin> could be supported too.

→ Compiled extension

When the runtime extension above is compiled by tusken generate, it's injected into the generated client as roughly the following code:

import * as tusken from 'tusken'

export interface DatabaseConfig extends tusken.DatabaseConfig {
  foo?: number
}

const DEFAULT_FOO = 1

class Database extends tusken.Database {
  private _foo: number

  constructor(config: DatabaseConfig) {
    super(config)
    this._foo = config.foo ?? DEFAULT_FOO
  }

  foo() {...}
}

export default new Database({
   /* generated options go here */
})

The generated Database subclass is shared by all extension modules. As said before, any conflicting private instance properties and global variables are renamed.

@aleclarson aleclarson added status: in progress Someone is working on this status: on hold Was in progress, but not currently and removed status: in progress Someone is working on this labels Sep 8, 2022
@aleclarson
Copy link
Contributor Author

aleclarson commented Sep 11, 2022

Partial plugins

In your Tusken config, you can specify which extensions of a plugin you wish to use:

export default defineConfig({
  include: [
    // The default if a plugin isn't specified, but required if the package name 
    // doesn't include "tusken-plugin-" or similar
    'tusken-plugin-admin/*',
    // Use only the "map" extension from the tusken-plugin-array package.
    'tusken-plugin-array/map',
})

The include array will have its types generated so it can warn you about typos and give you auto-completion.

Probably also want support for shorthand objects:

{ 'tusken-plugin-array': ['map', 'forEach'] },

And we should probably just omit the tusken-plugin part?

'array/*',
'array/map',
{ array: ['map', 'filter'] },

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request status: on hold Was in progress, but not currently
Projects
None yet
Development

No branches or pull requests

1 participant