@zudojs/plugins 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -29
  3. package/dist/index.d.ts +34 -13
  4. package/dist/index.js +28 -10
  5. package/dist/pluginDependencies/dependencyResolver.core.d.ts +47 -6
  6. package/dist/pluginDependencies/dependencyResolver.core.js +108 -46
  7. package/dist/pluginDependencies/index.d.ts +6 -2
  8. package/dist/pluginDependencies/index.js +4 -1
  9. package/dist/pluginDependencies/versionCheck.core.d.ts +67 -0
  10. package/dist/pluginDependencies/versionCheck.core.js +199 -0
  11. package/dist/pluginDiagnostics/pluginDiagnostic.core.d.ts +9 -0
  12. package/dist/pluginDiagnostics/pluginDiagnostic.core.js +16 -12
  13. package/dist/pluginIntegration/index.d.ts +2 -1
  14. package/dist/pluginIntegration/index.js +1 -1
  15. package/dist/pluginIntegration/pluginContext.core.d.ts +35 -5
  16. package/dist/pluginIntegration/pluginContext.core.js +28 -5
  17. package/dist/pluginLifecycle/pluginLifecycle.core.d.ts +42 -0
  18. package/dist/pluginLifecycle/pluginLifecycle.core.js +132 -70
  19. package/dist/pluginManager/pluginManager.core.d.ts +121 -3
  20. package/dist/pluginManager/pluginManager.core.js +282 -47
  21. package/dist/pluginRegistry/pluginRegistry.core.d.ts +15 -6
  22. package/dist/pluginRegistry/pluginRegistry.core.js +6 -1
  23. package/dist/pluginTypes/index.d.ts +1 -1
  24. package/dist/pluginTypes/pluginContext.type.d.ts +11 -3
  25. package/dist/pluginTypes/pluginState.type.js +6 -3
  26. package/package.json +26 -15
  27. package/dist/.tsbuildinfo +0 -1
  28. package/dist/index.d.ts.map +0 -1
  29. package/dist/index.js.map +0 -1
  30. package/dist/pluginDependencies/dependencyResolver.core.d.ts.map +0 -1
  31. package/dist/pluginDependencies/dependencyResolver.core.js.map +0 -1
  32. package/dist/pluginDependencies/index.d.ts.map +0 -1
  33. package/dist/pluginDependencies/index.js.map +0 -1
  34. package/dist/pluginDiagnostics/index.d.ts.map +0 -1
  35. package/dist/pluginDiagnostics/index.js.map +0 -1
  36. package/dist/pluginDiagnostics/pluginDiagnostic.core.d.ts.map +0 -1
  37. package/dist/pluginDiagnostics/pluginDiagnostic.core.js.map +0 -1
  38. package/dist/pluginEvents/index.d.ts.map +0 -1
  39. package/dist/pluginEvents/index.js.map +0 -1
  40. package/dist/pluginEvents/pluginEvent.core.d.ts.map +0 -1
  41. package/dist/pluginEvents/pluginEvent.core.js.map +0 -1
  42. package/dist/pluginIntegration/index.d.ts.map +0 -1
  43. package/dist/pluginIntegration/index.js.map +0 -1
  44. package/dist/pluginIntegration/pluginContext.core.d.ts.map +0 -1
  45. package/dist/pluginIntegration/pluginContext.core.js.map +0 -1
  46. package/dist/pluginLifecycle/pluginLifecycle.core.d.ts.map +0 -1
  47. package/dist/pluginLifecycle/pluginLifecycle.core.js.map +0 -1
  48. package/dist/pluginManager/pluginManager.core.d.ts.map +0 -1
  49. package/dist/pluginManager/pluginManager.core.js.map +0 -1
  50. package/dist/pluginRegistry/index.d.ts.map +0 -1
  51. package/dist/pluginRegistry/index.js.map +0 -1
  52. package/dist/pluginRegistry/pluginRegistry.core.d.ts.map +0 -1
  53. package/dist/pluginRegistry/pluginRegistry.core.js.map +0 -1
  54. package/dist/pluginTypes/index.d.ts.map +0 -1
  55. package/dist/pluginTypes/index.js.map +0 -1
  56. package/dist/pluginTypes/plugin.type.d.ts.map +0 -1
  57. package/dist/pluginTypes/plugin.type.js.map +0 -1
  58. package/dist/pluginTypes/pluginContext.type.d.ts.map +0 -1
  59. package/dist/pluginTypes/pluginContext.type.js.map +0 -1
  60. package/dist/pluginTypes/pluginDependency.type.d.ts.map +0 -1
  61. package/dist/pluginTypes/pluginDependency.type.js.map +0 -1
  62. package/dist/pluginTypes/pluginMetadata.type.d.ts.map +0 -1
  63. package/dist/pluginTypes/pluginMetadata.type.js.map +0 -1
  64. package/dist/pluginTypes/pluginState.type.d.ts.map +0 -1
  65. package/dist/pluginTypes/pluginState.type.js.map +0 -1
@@ -1,9 +1,20 @@
1
1
  import { PluginRegistryImpl } from "../pluginRegistry/pluginRegistry.core.js";
2
2
  import { DependencyResolver, assertResolutionValid, } from "../pluginDependencies/dependencyResolver.core.js";
3
+ import { assertDependencyVersions } from "../pluginDependencies/versionCheck.core.js";
3
4
  import { LifecycleController } from "../pluginLifecycle/pluginLifecycle.core.js";
4
- import { PluginAlreadyRegisteredError, PluginDependencyCycleError, PluginDependencyError, PluginInitializationError, PluginNotFoundError, PluginRegistrationError, } from "@zudojs/errors";
5
- import { PLUGIN_EVENTS } from "../pluginEvents/pluginEvent.core.js";
6
- import { buildDiagnosticReport, createHealthyHealth, createUnhealthyHealth, } from "../pluginDiagnostics/pluginDiagnostic.core.js";
5
+ import { PluginError, PluginRegistrationError, PluginStateError, } from "@zudojs/errors";
6
+ import { createOwnedPluginContext } from "../pluginIntegration/pluginContext.core.js";
7
+ import { buildDiagnosticReport } from "../pluginDiagnostics/pluginDiagnostic.core.js";
8
+ import { PLUGIN_EVENTS, createPluginLifecycleEvent, } from "../pluginEvents/pluginEvent.core.js";
9
+ /**
10
+ * States from which a plugin still owns resources that must be released.
11
+ */
12
+ const DISPOSABLE_STATES = new Set([
13
+ "installed",
14
+ "initialized",
15
+ "stopped",
16
+ "failed",
17
+ ]);
7
18
  /**
8
19
  * Plugin manager coordinates registration, dependency resolution, lifecycle, and disposal.
9
20
  */
@@ -12,19 +23,78 @@ export class PluginManager {
12
23
  resolver;
13
24
  lifecycle;
14
25
  plugins = new Map();
15
- constructor() {
26
+ options;
27
+ /**
28
+ * Dependency-first order from the last successful resolution.
29
+ *
30
+ * Shutdown reverses this rather than registration order: tearing down
31
+ * in registration order destroys a dependency while its dependents are
32
+ * still using it.
33
+ */
34
+ startupOrder = [];
35
+ starting = false;
36
+ /**
37
+ * Per-plugin context views and their abort handles.
38
+ *
39
+ * Each plugin gets a context whose `onDispose` and
40
+ * `registerDisposable` write to that plugin's own disposables list —
41
+ * the list the lifecycle actually drains — and whose `signal` this
42
+ * manager aborts on shutdown.
43
+ */
44
+ contexts = new Map();
45
+ constructor(options = {}) {
16
46
  this.registry = new PluginRegistryImpl();
17
47
  this.resolver = new DependencyResolver();
18
- this.lifecycle = new LifecycleController();
48
+ this.lifecycle = new LifecycleController(options.hookTimeout !== undefined
49
+ ? { hookTimeout: options.hookTimeout }
50
+ : {});
51
+ this.options = options;
19
52
  }
20
- register(plugin) {
53
+ /**
54
+ * Registers a plugin.
55
+ *
56
+ * @throws {PluginAlreadyRegisteredError} when the name is taken, so
57
+ * callers can implement idempotent registration.
58
+ */
59
+ register(plugin, options) {
60
+ if (typeof plugin?.metadata?.name !== "string" ||
61
+ plugin.metadata.name.length === 0) {
62
+ throw new PluginRegistrationError("Plugin metadata must include a non-empty name.");
63
+ }
64
+ const allowed = this.options.allowedCapabilities;
65
+ if (allowed) {
66
+ const requested = plugin.metadata.capabilities ?? [];
67
+ const denied = requested.filter((capability) => !allowed.includes(capability));
68
+ if (denied.length > 0) {
69
+ throw new PluginRegistrationError(`Plugin "${plugin.metadata.name}" requests capabilities that are not granted: ${denied.join(", ")}.`, plugin.metadata.name);
70
+ }
71
+ }
21
72
  try {
22
- this.registry.register(plugin);
73
+ this.registry.register(plugin, options);
23
74
  this.plugins.set(plugin.metadata.name, plugin);
75
+ this.emitRegistered(plugin);
24
76
  }
25
77
  catch (error) {
26
- throw new PluginRegistrationError(error.message, plugin.metadata.name);
78
+ // Typed plugin errors already say what went wrong and let callers
79
+ // branch on the cause; only unexpected failures are wrapped.
80
+ if (error instanceof PluginError) {
81
+ throw error;
82
+ }
83
+ throw new PluginRegistrationError(error instanceof Error ? error.message : String(error), plugin.metadata.name);
84
+ }
85
+ }
86
+ /**
87
+ * Removes a plugin that has not been started.
88
+ *
89
+ * Keeps the manager's own view in step with the registry; leaving a
90
+ * removed plugin in `plugins` would keep it in dependency resolution.
91
+ */
92
+ unregister(name) {
93
+ const removed = this.registry.remove(name);
94
+ if (removed) {
95
+ this.plugins.delete(name);
27
96
  }
97
+ return removed;
28
98
  }
29
99
  get(name) {
30
100
  return this.registry.get(name)?.plugin;
@@ -35,66 +105,231 @@ export class PluginManager {
35
105
  list() {
36
106
  return this.registry.list().map((r) => r.plugin);
37
107
  }
108
+ /**
109
+ * Installs, initializes and starts every plugin in dependency order.
110
+ *
111
+ * A failure anywhere rolls back: everything already brought up is
112
+ * stopped and disposed before the error is rethrown, so an aborted
113
+ * startup does not strand resources with no route to release them.
114
+ */
38
115
  async start(context) {
39
- const resolution = this.resolver.resolve(this.toDependencyMap());
40
- assertResolutionValid(resolution);
41
- const ordered = resolution.ordered;
42
- for (const name of ordered) {
43
- const registered = this.registry.get(name);
44
- if (!registered || registered.state === "disposed") {
45
- continue;
116
+ if (this.starting) {
117
+ throw new PluginRegistrationError("Plugin manager start is already in progress.");
118
+ }
119
+ this.starting = true;
120
+ try {
121
+ const resolution = this.resolver.resolve(this.toDependencyMap());
122
+ assertResolutionValid(resolution);
123
+ if (this.options.checkVersions ?? true) {
124
+ assertDependencyVersions(this.plugins);
125
+ }
126
+ this.startupOrder = resolution.ordered;
127
+ // A disposed plugin has released its resources and the state
128
+ // machine offers no way back. `start()` used to skip such plugins
129
+ // silently — so a second `start()` after `stop()` resolved with
130
+ // nothing running, and after a rolled-back startup it brought up
131
+ // still-registered dependents on top of disposed dependencies.
132
+ for (const name of this.startupOrder) {
133
+ const registered = this.registry.get(name);
134
+ if (registered?.state === "disposed") {
135
+ throw new PluginStateError(name, "disposed", "installing");
136
+ }
137
+ }
138
+ try {
139
+ for (const name of this.startupOrder) {
140
+ const registered = this.registry.get(name);
141
+ if (!registered)
142
+ continue;
143
+ // Guarded so a restart — where plugins are already installed
144
+ // and merely stopped — re-runs only the phases it needs.
145
+ if (registered.state === "registered") {
146
+ await this.lifecycle.install(registered, this.contextFor(registered, context));
147
+ }
148
+ }
149
+ for (const name of this.startupOrder) {
150
+ const registered = this.registry.get(name);
151
+ if (!registered)
152
+ continue;
153
+ if (registered.state === "installed") {
154
+ await this.lifecycle.initialize(registered, this.contextFor(registered, context));
155
+ }
156
+ }
157
+ for (const name of this.startupOrder) {
158
+ const registered = this.registry.get(name);
159
+ if (!registered)
160
+ continue;
161
+ if (registered.state === "initialized" ||
162
+ registered.state === "stopped") {
163
+ await this.lifecycle.start(registered, this.contextFor(registered, context));
164
+ }
165
+ }
166
+ }
167
+ catch (error) {
168
+ await this.rollback(context);
169
+ throw error;
46
170
  }
47
- await this.lifecycle.install(registered, context);
48
171
  }
49
- for (const name of ordered) {
50
- const registered = this.registry.get(name);
51
- if (!registered || registered.state === "disposed") {
172
+ finally {
173
+ this.starting = false;
174
+ }
175
+ }
176
+ /**
177
+ * Stops and disposes every plugin, in reverse dependency order.
178
+ *
179
+ * Teardown continues past a failing plugin so one bad `stop` cannot
180
+ * strand the rest, and every failure is reported through `onError`
181
+ * rather than swallowed.
182
+ */
183
+ async stop(context) {
184
+ for (const registered of this.teardownOrder()) {
185
+ if (registered.state !== "started")
52
186
  continue;
187
+ try {
188
+ await this.lifecycle.stop(registered, this.contextFor(registered, context));
53
189
  }
54
- if (registered.state === "installed") {
55
- await this.lifecycle.initialize(registered, context);
190
+ catch (error) {
191
+ this.report(error, registered.plugin.metadata.name);
56
192
  }
57
193
  }
58
- for (const name of ordered) {
59
- const registered = this.registry.get(name);
60
- if (!registered || registered.state === "disposed") {
194
+ for (const registered of this.teardownOrder()) {
195
+ // Anything that still holds resources is disposed, including
196
+ // plugins that were installed or initialized but never started
197
+ // because an earlier plugin failed.
198
+ if (!DISPOSABLE_STATES.has(registered.state))
61
199
  continue;
200
+ const name = registered.plugin.metadata.name;
201
+ try {
202
+ // Abort first so work the plugin started sees the shutdown
203
+ // before its disposables are released underneath it.
204
+ this.abortContext(name);
205
+ await this.lifecycle.dispose(registered, this.contextFor(registered, context));
206
+ }
207
+ catch (error) {
208
+ this.report(error, name);
62
209
  }
63
- if (registered.state === "initialized") {
64
- await this.lifecycle.start(registered, context);
210
+ finally {
211
+ this.contexts.delete(name);
65
212
  }
66
213
  }
67
214
  }
68
- async stop(context) {
69
- const plugins = this.registry.list();
70
- const reversed = [...plugins].reverse();
71
- for (const registered of reversed) {
215
+ diagnostics() {
216
+ const plugins = this.registry.list().map((registered) => ({
217
+ plugin: registered.plugin,
218
+ state: registered.state,
219
+ failed: registered.failed,
220
+ error: registered.error,
221
+ }));
222
+ return buildDiagnosticReport(plugins);
223
+ }
224
+ /**
225
+ * Tears down everything brought up by a failed startup.
226
+ */
227
+ async rollback(context) {
228
+ for (const registered of this.teardownOrder()) {
72
229
  if (registered.state === "started") {
73
230
  try {
74
- await this.lifecycle.stop(registered, context);
231
+ await this.lifecycle.stop(registered, this.contextFor(registered, context));
75
232
  }
76
- catch {
77
- continue;
233
+ catch (error) {
234
+ this.report(error, registered.plugin.metadata.name);
78
235
  }
79
236
  }
80
237
  }
81
- for (const registered of reversed) {
82
- if (registered.state === "stopped" || registered.state === "failed") {
83
- try {
84
- await this.lifecycle.dispose(registered, context);
85
- }
86
- catch {
87
- continue;
88
- }
238
+ for (const registered of this.teardownOrder()) {
239
+ if (!DISPOSABLE_STATES.has(registered.state))
240
+ continue;
241
+ const name = registered.plugin.metadata.name;
242
+ try {
243
+ this.abortContext(name);
244
+ await this.lifecycle.dispose(registered, this.contextFor(registered, context));
245
+ }
246
+ catch (error) {
247
+ this.report(error, name);
248
+ }
249
+ finally {
250
+ this.contexts.delete(name);
89
251
  }
90
252
  }
91
253
  }
92
- diagnostics() {
93
- const plugins = this.registry.list().map((registered) => ({
94
- plugin: registered.plugin,
95
- state: registered.state,
96
- }));
97
- return buildDiagnosticReport(plugins);
254
+ /**
255
+ * Registered plugins in reverse dependency order.
256
+ *
257
+ * Falls back to reverse registration order for plugins registered
258
+ * after the last resolution, which is the best available guess.
259
+ */
260
+ teardownOrder() {
261
+ const seen = new Set();
262
+ const ordered = [];
263
+ for (let i = this.startupOrder.length - 1; i >= 0; i -= 1) {
264
+ const name = this.startupOrder[i];
265
+ const registered = this.registry.get(name);
266
+ if (registered) {
267
+ seen.add(name);
268
+ ordered.push(registered);
269
+ }
270
+ }
271
+ const remaining = this.registry
272
+ .list()
273
+ .filter((registered) => !seen.has(registered.plugin.metadata.name))
274
+ .reverse();
275
+ return [...ordered, ...remaining];
276
+ }
277
+ /**
278
+ * Returns the plugin's own context view, creating it on first use.
279
+ *
280
+ * The base context supplies the shared services; only the identity,
281
+ * the disposables collection and the abort signal are per-plugin.
282
+ */
283
+ contextFor(registered, base) {
284
+ const name = registered.plugin.metadata.name;
285
+ const existing = this.contexts.get(name);
286
+ if (existing) {
287
+ return existing.context;
288
+ }
289
+ const owned = createOwnedPluginContext(registered.plugin.metadata, {
290
+ container: base.container,
291
+ config: base.config,
292
+ logger: base.logger,
293
+ events: base.events,
294
+ disposables: registered.disposables,
295
+ });
296
+ this.contexts.set(name, { context: owned.context, abort: owned.abort });
297
+ return owned.context;
298
+ }
299
+ /**
300
+ * Aborts a plugin's signal, keeping the context available.
301
+ *
302
+ * The entry stays so `dispose` still receives the same — now aborted —
303
+ * context; removing it here would hand the dispose hook a fresh
304
+ * context whose signal had never fired.
305
+ */
306
+ abortContext(name, reason) {
307
+ this.contexts.get(name)?.abort(reason);
308
+ }
309
+ /**
310
+ * Emits `plugin:registered`, containing a throwing subscriber so a bad
311
+ * listener cannot fail the registration that triggered it.
312
+ */
313
+ emitRegistered(plugin) {
314
+ const events = this.options.events;
315
+ if (!events) {
316
+ return;
317
+ }
318
+ try {
319
+ events.emit(PLUGIN_EVENTS.REGISTERED, createPluginLifecycleEvent(plugin.metadata, "registered"));
320
+ }
321
+ catch (error) {
322
+ this.report(error, plugin.metadata.name);
323
+ }
324
+ }
325
+ report(error, pluginName) {
326
+ if (this.options.onError) {
327
+ this.options.onError(error, pluginName);
328
+ return;
329
+ }
330
+ queueMicrotask(() => {
331
+ console.error(`[@zudojs/plugins] Plugin "${pluginName}" failed during teardown.`, error);
332
+ });
98
333
  }
99
334
  toDependencyMap() {
100
335
  const map = new Map();
@@ -1,5 +1,6 @@
1
1
  import type { Plugin } from "../pluginTypes/plugin.type.js";
2
2
  import type { PluginState } from "../pluginTypes/pluginState.type.js";
3
+ import type { PluginDisposable } from "../pluginTypes/pluginContext.type.js";
3
4
  /**
4
5
  * Internal representation of a registered plugin.
5
6
  */
@@ -7,13 +8,21 @@ export interface RegisteredPlugin<TPlugin extends Plugin = Plugin> {
7
8
  readonly plugin: TPlugin;
8
9
  state: PluginState;
9
10
  readonly options?: unknown;
10
- readonly disposables: Array<{
11
- dispose(): void | Promise<void>;
12
- }>;
13
- registerDisposable(disposable: {
14
- dispose(): void | Promise<void>;
15
- }): void;
11
+ readonly disposables: PluginDisposable[];
12
+ /**
13
+ * Whether this plugin failed at any point in its lifecycle.
14
+ *
15
+ * Tracked separately from `state` because a failed plugin is disposed
16
+ * during rollback, which would otherwise erase every trace of the
17
+ * failure from diagnostics.
18
+ */
19
+ failed: boolean;
20
+ /** The error that caused the failure, if any. */
21
+ error?: unknown;
22
+ registerDisposable(disposable: PluginDisposable): void;
16
23
  setState(state: PluginState): void;
24
+ /** Records a lifecycle failure. */
25
+ setError(error: unknown): void;
17
26
  }
18
27
  /**
19
28
  * Plugin registry interface.
@@ -1,4 +1,4 @@
1
- import { PluginAlreadyRegisteredError, PluginNotFoundError, PluginStateError, } from "@zudojs/errors";
1
+ import { PluginAlreadyRegisteredError, PluginStateError } from "@zudojs/errors";
2
2
  /**
3
3
  * Default plugin registry implementation.
4
4
  */
@@ -15,12 +15,17 @@ export class PluginRegistryImpl {
15
15
  state: "registered",
16
16
  options,
17
17
  disposables,
18
+ failed: false,
18
19
  registerDisposable(disposable) {
19
20
  disposables.push(disposable);
20
21
  },
21
22
  setState(state) {
22
23
  registered.state = state;
23
24
  },
25
+ setError(error) {
26
+ registered.failed = true;
27
+ registered.error = error;
28
+ },
24
29
  };
25
30
  this.plugins.set(name, registered);
26
31
  }
@@ -6,7 +6,7 @@
6
6
  export type { PluginState } from "./pluginState.type.js";
7
7
  export type { PluginMetadata } from "./pluginMetadata.type.js";
8
8
  export type { PluginDependency } from "./pluginDependency.type.js";
9
- export type { PluginContext, PluginContainer, PluginConfig, PluginLogger, PluginEvents, } from "./pluginContext.type.js";
9
+ export type { PluginContext, PluginContainer, PluginConfig, PluginLogger, PluginEvents, PluginDisposable, } from "./pluginContext.type.js";
10
10
  export type { Plugin } from "./plugin.type.js";
11
11
  export type { PluginErrorOptions } from "@zudojs/errors";
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -27,6 +27,12 @@ export interface PluginEvents {
27
27
  off(event: string, handler: (event: unknown) => void): void;
28
28
  emit(event: string, payload: unknown): void;
29
29
  }
30
+ /**
31
+ * Something a plugin registers so the manager releases it on shutdown.
32
+ */
33
+ export interface PluginDisposable {
34
+ dispose(): void | Promise<void>;
35
+ }
30
36
  /**
31
37
  * Controlled context provided to plugins during lifecycle operations.
32
38
  */
@@ -36,10 +42,12 @@ export interface PluginContext {
36
42
  readonly config?: PluginConfig;
37
43
  readonly logger?: PluginLogger;
38
44
  readonly events?: PluginEvents;
45
+ /**
46
+ * Aborted when the plugin system shuts down, so long-lived work
47
+ * started by the plugin can stop.
48
+ */
39
49
  readonly signal: AbortSignal;
40
50
  onDispose(handler: () => void | Promise<void>): void;
41
- registerDisposable(disposable: {
42
- dispose(): void | Promise<void>;
43
- }): void;
51
+ registerDisposable(disposable: PluginDisposable): void;
44
52
  }
45
53
  //# sourceMappingURL=pluginContext.type.d.ts.map
@@ -2,11 +2,14 @@
2
2
  * Valid state transitions for the plugin state machine.
3
3
  */
4
4
  export const VALID_STATE_TRANSITIONS = {
5
- registered: ["installing"],
5
+ registered: ["installing", "disposing"],
6
6
  installing: ["installed", "failed"],
7
- installed: ["initializing", "stopping"],
7
+ // A plugin that installed but never started still holds resources, so
8
+ // it must have a route to disposal; without one an aborted startup
9
+ // stranded it permanently.
10
+ installed: ["initializing", "stopping", "disposing", "failed"],
8
11
  initializing: ["initialized", "failed"],
9
- initialized: ["starting", "stopping"],
12
+ initialized: ["starting", "stopping", "disposing", "failed"],
10
13
  starting: ["started", "failed"],
11
14
  started: ["stopping"],
12
15
  stopping: ["stopped", "failed"],
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@zudojs/plugins",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
4
  "description": "Plugin system for extending Zudojs applications with modular capabilities.",
5
5
  "license": "MIT",
6
+ "author": {
7
+ "name": "Oluwayemi Oyinlola",
8
+ "url": "https://github.com/oyinlola-tech"
9
+ },
6
10
  "type": "module",
7
11
  "main": "./dist/index.js",
8
12
  "module": "./dist/index.js",
@@ -14,23 +18,19 @@
14
18
  }
15
19
  },
16
20
  "files": [
17
- "dist"
21
+ "dist",
22
+ "!dist/**/*.map",
23
+ "!dist/**/*.tsbuildinfo",
24
+ "!dist/.tsbuildinfo"
18
25
  ],
19
- "scripts": {
20
- "build": "tsc -p tsconfig.json",
21
- "typecheck": "tsc -p tsconfig.json --noEmit",
22
- "clean": "rm -rf dist",
23
- "test": "vitest run",
24
- "test:watch": "vitest"
25
- },
26
26
  "dependencies": {
27
- "@zudojs/errors": "0.1.0",
28
- "@zudojs/constants": "0.1.0",
29
- "@zudojs/types": "0.1.0"
27
+ "@zudojs/errors": "1.0.1",
28
+ "@zudojs/constants": "1.0.1",
29
+ "@zudojs/types": "1.0.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^26.4.1",
33
- "typescript": "^7.0.2",
33
+ "typescript": "7.0.2",
34
34
  "vitest": "^4.1.11"
35
35
  },
36
36
  "engines": {
@@ -45,8 +45,19 @@
45
45
  "extensions"
46
46
  ],
47
47
  "homepage": "https://github.com/oyinlola-tech/zudo#readme",
48
+ "bugs": {
49
+ "url": "https://github.com/oyinlola-tech/zudo/issues"
50
+ },
48
51
  "repository": {
49
52
  "type": "git",
50
- "url": "https://github.com/oyinlola-tech/zudo"
53
+ "url": "https://github.com/oyinlola-tech/zudo",
54
+ "directory": "packages/plugins"
55
+ },
56
+ "scripts": {
57
+ "build": "tsc -p tsconfig.json",
58
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
59
+ "clean": "rm -rf dist",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest"
51
62
  }
52
- }
63
+ }