Skip to content

Commit 41b735a

Browse files
authored
docs(README): add more usage examples and API reference (#66)
1 parent cba90c6 commit 41b735a

File tree

2 files changed

+107
-34
lines changed

2 files changed

+107
-34
lines changed

README.md

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,121 @@
55
[![@latest](https://img.shields.io/npm/v/javascript-plugin-architecture-with-typescript-definitions.svg)](https://www.npmjs.com/package/javascript-plugin-architecture-with-typescript-definitions)
66
[![Build Status](https://github.com/gr2m/javascript-plugin-architecture-with-typescript-definitions/workflows/Test/badge.svg)](https://github.com/gr2m/javascript-plugin-architecture-with-typescript-definitions/actions/workflows/test.yml)
77

8-
The goal of this repository is to provide a template of a simple plugin Architecture which allows plugins to be created and authored as separate npm modules and shared as official or 3rd party plugins. It also permits the plugins to extend the types for the constructor options.
8+
The goal of this repository is to provide a template for a simple plugin Architecture which allows plugin authors to extend the base API as well as extend its constructor options. A custom class can be composed of the core Base class, a set of plugins and default options and distributed as new package, with full TypeScript for added APIs and constructor options.
99

1010
## Usage
1111

12-
[Try it in TypeScript's playground editor](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgIQIYGcCmcC+cBmUEIcARAFaoBuGAxlMGDALRgA2ArgObAB2zqKLQAWwGJlowOUTMwDuY4cxgBPMJnT1GLACaZ8fMcAi90pANwAoS-g69Jx3nBAqAYhAgAFTj14AKPnQYVHtMAC4UDEwASkRLODgZKSgnBHiEgg8Iv1iAXgA+MnwPUgAadJwrHGtbexhHZxU0KG9uPgDTYNCItCxYtISk6VT0hIAjQWy8wtIJqDKKqpq7BxM4DCxYAGUYBl4uP3QOMfIJGAigva5+6staEyC4dwgAFQ14XMisADoFGGFWr50H4ANouZ6AvgAXWiVnunUyr3ecE+vEwcieHjeQRyVg2mG2uz4B2KSKC31JOVh1nhj2ezWxHy+mF+ikhplB4I87NKjWa7JhcIe8FJDORqPRmIgYpx1PxhKuflFgkZFI8VLx6E2MB2iuVUFVcw1QA)
12+
[Try it in TypeScript's playground editor](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgIQIYGcCmcC+cBmUEIcARAFaoBuGAxlMGDALRgA2ArgObAB2zqKLQAWwGJlowOUTMwDuY4cxgBPMJnT1GLACaZ8fMcAi90pANwAoS3tptB2EBB0c22CtToMmrTj36CImISUjLyispqGlo+ega8RiZmiJZwcLyoIBpgqLTYaFgpaWl84lD4udgA8kzGpkXFafgQEABccOgwDLxcVo04qbiWA5b4HLySdXAgKgBiLQAKfnwAFHydqBOY7QWYADRwELVJOxiYAHQ1MHXoAJQNMqG8DU0t7Sv3ALwAfIfHpudmhA4AAfEFkABGglIe0GOCsIzGE2uJmmKjQUCW3FW6xgmzypyw9wQg0e0meJMaUKg7y+v1I1JhcIR1loSXgAFl0Wc4J8UGdzgoYMIsf50CsANozeYQUV8A4zDFy3gAXVugsUABF9KhXDBxZSCG9IdDYThblZLGzTPBFTy+bxMHI4FzdiskED2gzUAAvUi4C2WO1YQEtD7mOAAekjHS6fC4Qe5Iep4ajMc63QTQA)
13+
14+
### Export new class `MyBase` with two plugins and default options:
1315

1416
```ts
17+
// import the Base class
1518
import { Base } from "javascript-plugin-architecture-with-typescript-definitions";
1619

17-
function myFooPlugin(instance: Base) {
18-
return {
19-
foo: () => "foo",
20-
};
21-
}
20+
// import a set of plugins
21+
import { myFooPlugin } from "@example/my-foo-plugin";
22+
import { myBarPlugin } from "./my-bar-plugin";
2223

23-
function myBarPlugin(instance: Base) {
24-
return {
25-
bar: () => "bar",
26-
};
27-
}
24+
export const MyBase = Base.withPlugins([myFooPlugin, myBarPlugin]).withDefaults(
25+
{
26+
foo: "bar",
27+
}
28+
);
29+
```
2830

29-
const FooTest = Base.withPlugins([myFooPlugin]);
30-
const fooTest = new FooTest();
31-
fooTest.foo(); // has full TypeScript intellisense
31+
When importing `MyBase` and instantiating it, the `MyBase` constructor has type support for the new optional `foo` option as well as the `.foo()` and `.bar()` methods addded by the respective plugins.
3232

33-
const FooBarTest = Base.withPlugins([myFooPlugin, myBarPlugin]);
34-
const fooBarTest = new FooBarTest();
35-
fooBarTest.foo(); // has full TypeScript intellisense
36-
fooBarTest.bar(); // has full TypeScript intellisense
33+
```ts
34+
import { MyBase } from "@example/my-base";
35+
36+
const myBase = new MyBase({
37+
// has full TypeScript intellisense
38+
foo: "bar",
39+
});
40+
myBase.foo(); // has full TypeScript intellisense
41+
myBase.bar(); // has full TypeScript intellisense
3742
```
3843

39-
The constructor accepts an optional `options` object which is passed to the plugins as second argument and stored in `instance.options`. Default options can be set using `Base.withDefaults(options)`.
44+
### Create plugin which extends the API as well as the constructor options type
4045

4146
```js
42-
const BaseWithOptions = Base.withDefaults({ foo: "bar" });
43-
const instance = new BaseWithOptions();
44-
instance.options; // {foo: 'bar'}
45-
```
46-
47-
Note that in for TypeScript to recognize the new option, you have to extend the `Base.Option` intererface.
47+
import { Base } from "javascript-plugin-architecture-with-typescript-definitions";
4848

49-
```ts
5049
declare module "javascript-plugin-architecture-with-typescript-definitions" {
5150
namespace Base {
5251
interface Options {
53-
foo: string;
52+
foo?: string;
5453
}
5554
}
5655
}
56+
57+
export function myFooPlugin(base: Base, options: Base.options) {
58+
return {
59+
foo() => options.foo || "bar",
60+
}
61+
}
5762
```
5863

59-
See also the [`required-options` example](examples/required-options).
64+
## API
65+
66+
### static `.withPlugins(plugins)`
67+
68+
Returns a new class with `.plugins` added to parent classes `.plugins` array. All plugins will be applied to instances.
69+
70+
### static `.withDefaults(options)`
6071

61-
The `Base` class also has two static properties
72+
Returns a new class with `.defaults` merged with the parent classes `.defaults` object. The defaults are applied to the options passed to the constructor when instantiated.
6273

63-
- `.defaults`: the default options for all instances
64-
- `.plugins`: the list of plugins applied to all instances
74+
### static `.plugins`
6575

66-
When creating a new class with `.withPlugins()` and `.defaults()`, the static properties of the returned class are set accordingly.
76+
`Base.plugins` is an empty array by default. It is extended on derived classes using `.withPlugins(plugins)`.
77+
78+
### static `.defaults`
79+
80+
`Base.defaults` is an empty object by default. It is extended on derived classes using `.withDefaults(plugins)`.
81+
82+
### Constructor
83+
84+
The constructor accepts one argument which is optional by default
85+
86+
```ts
87+
new Base(options);
88+
```
89+
90+
If the `Base.Options` interface has been extended with required keys, then the `options` argument becomes required, and all required `Base.Options` keys must be set.
91+
92+
### `.options`
93+
94+
The `.options` key is set on all instances. It's merged from from the constructor's `.defaults` object and the options passed to the constructor
6795

6896
```js
69-
const MyBase = Base.withDefaults({ foo: "bar" });
97+
const BaseWithOptions = Base.withDefaults({ foo: "bar" });
98+
const instance = new BaseWithOptions();
99+
instance.options; // {foo: 'bar'}
100+
```
101+
102+
Note that in for TypeScript to recognize the new option, you have to extend the `Base.Option` intererface.
103+
104+
### Other instance propreties and methods
105+
106+
Instance properties and methods can be added using plugins. Example:
107+
108+
```ts
109+
function myPlugin(base: Base, options: Base.options) {
110+
return {
111+
myMethod() {
112+
/* do something here */
113+
},
114+
myProperty: "", // set to something useful
115+
};
116+
}
117+
const MyBase = Base.plugins([myPlugin]);
118+
const myBase = new MyBase();
119+
120+
// this method and property is now set
121+
myBase.myMethod();
122+
myBase.myProperty;
70123
```
71124

72125
### Defaults

examples/required-options/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,23 @@ With that extension, the same code will have a type error
2727
// TS Error: Property 'myRequiredUserOption' is missing in type '{}' but required in type 'Options'
2828
const base = new Base({});
2929
```
30+
31+
Extending the `Base.Options` interface is useful to plugin developers, as options are passed as second argument to a plugin function.
32+
33+
```ts
34+
import { Base } from "javascript-plugin-architecture-with-typescript-definitions";
35+
36+
declare module "javascript-plugin-architecture-with-typescript-definitions" {
37+
namespace Base {
38+
interface Options {
39+
myPluginOption: string;
40+
}
41+
}
42+
}
43+
44+
export function myPlugin(base: Base, options: Base.Options) {
45+
options.myPluginOption; // is now typed as `string`
46+
}
47+
```
48+
49+
And users of the plugin will get a type error if they don't set `myPluginOption` on the instructor.

0 commit comments

Comments
 (0)