Skip to content

Commit 2a9c7b4

Browse files
feat: use class inheritance for plug-in api [wip]
1 parent 653935b commit 2a9c7b4

File tree

3 files changed

+124
-38
lines changed

3 files changed

+124
-38
lines changed

packages/indiekit/lib/plugin.js

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { createRequire } from "node:module";
2+
import path from "node:path";
3+
4+
import { IndiekitError } from "@indiekit/error";
5+
import makeDebug from "debug";
6+
7+
import { getPluginId } from "./plugins.js";
8+
9+
const debug = makeDebug(`indiekit:plugin`);
10+
11+
export class IndiekitPlugin {
12+
constructor(Indiekit) {
13+
this.indiekit = Indiekit;
14+
this.name = undefined;
15+
this.packageName = undefined;
16+
this.options = {};
17+
}
18+
19+
static async register(indiekit, packageName) {
20+
debug(`Registering ${packageName}`);
21+
22+
const plugin = new this(indiekit);
23+
plugin.packageName = packageName;
24+
plugin.options = indiekit.config[packageName];
25+
plugin.name = plugin.name || packageName;
26+
27+
// Initiate plugin features
28+
await plugin.init();
29+
30+
// Add plugin to Indiekit
31+
indiekit.installedPlugins.add(plugin);
32+
33+
return plugin;
34+
}
35+
36+
get filePath() {
37+
const require = createRequire(import.meta.url);
38+
39+
try {
40+
return path.dirname(require.resolve(`${this.packageName}/package.json`));
41+
} catch (error) {
42+
throw new IndiekitError(
43+
`Could not resolve path for ${this.packageName}`,
44+
{
45+
cause: error,
46+
plugin: this.packageName,
47+
},
48+
);
49+
}
50+
}
51+
52+
get id() {
53+
return getPluginId(this.packageName);
54+
}
55+
56+
async init() {
57+
debug(`Initiating ${this.packageName}`);
58+
}
59+
}
60+
61+
export class IndiekitPostTypePlugin extends IndiekitPlugin {
62+
constructor(Indiekit) {
63+
super(Indiekit);
64+
65+
this.type = undefined;
66+
}
67+
68+
get config() {
69+
return {};
70+
}
71+
72+
addPostTypes() {
73+
// Override post type configuration with user options
74+
const postType = { ...this.config, ...this.options };
75+
76+
if (postType) {
77+
debug("Adding post type configuration for", this.type);
78+
this.indiekit.postTypes.set(this.type, {
79+
...this.indiekit.postTypes.get(this.type),
80+
...postType,
81+
});
82+
}
83+
}
84+
85+
get validationSchemas() {
86+
return {};
87+
}
88+
89+
addValidationSchemas() {
90+
const validationSchemas = this.validationSchemas;
91+
if (validationSchemas) {
92+
for (const [field, schema] of Object.entries(validationSchemas)) {
93+
debug("Adding validation schemas for", field);
94+
this.indiekit.validationSchemas.set(field, schema);
95+
}
96+
}
97+
}
98+
99+
async init() {
100+
await super.init();
101+
102+
this.addPostTypes();
103+
this.addValidationSchemas();
104+
}
105+
}

packages/indiekit/lib/plugins.js

+2-16
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,12 @@
1-
import { createRequire } from "node:module";
2-
import path from "node:path";
3-
const require = createRequire(import.meta.url);
4-
51
/**
62
* Add plug-ins to application configuration
73
* @param {object} Indiekit - Indiekit instance
84
*/
95
export async function getInstalledPlugins(Indiekit) {
106
for await (const pluginName of Indiekit.config.plugins) {
117
const { default: IndiekitPlugin } = await import(pluginName);
12-
const plugin = new IndiekitPlugin(Indiekit.config[pluginName]);
13-
14-
// Add plug-in file path
15-
plugin.filePath = path.dirname(require.resolve(pluginName));
16-
17-
// Add plug-in ID
18-
plugin.id = getPluginId(pluginName);
19-
20-
// Register plug-in functions
21-
if (plugin.init) {
22-
await plugin.init(Indiekit);
23-
Indiekit.installedPlugins.add(plugin);
8+
if (IndiekitPlugin.register) {
9+
await IndiekitPlugin.register(Indiekit, pluginName);
2410
}
2511
}
2612
}

packages/post-type-article/index.js

+17-22
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
const defaults = {
2-
name: "Article",
3-
fields: {
4-
name: { required: true },
5-
summary: {},
6-
content: { required: true },
7-
category: {},
8-
geo: {},
9-
"post-status": {},
10-
published: { required: true },
11-
visibility: {},
12-
},
13-
};
1+
import { IndiekitPostTypePlugin } from "../indiekit/lib/plugin.js";
142

15-
export default class ArticlePostType {
16-
constructor(options = {}) {
3+
export default class ArticlePostTypePlugin extends IndiekitPostTypePlugin {
4+
constructor(Indiekit) {
5+
super(Indiekit);
6+
7+
this.type = "article";
178
this.name = "Article post type";
18-
this.options = { ...defaults, ...options };
199
}
2010

2111
get config() {
2212
return {
23-
name: this.options.name,
13+
name: "Article",
2414
h: "entry",
25-
fields: this.options.fields,
15+
fields: {
16+
name: { required: true },
17+
summary: {},
18+
content: { required: true },
19+
category: {},
20+
geo: {},
21+
"post-status": {},
22+
published: { required: true },
23+
visibility: {},
24+
},
2625
};
2726
}
28-
29-
init(Indiekit) {
30-
Indiekit.addPostType("article", this);
31-
}
3227
}

0 commit comments

Comments
 (0)