@zudojs/plugins 1.0.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.
package/README.md CHANGED
@@ -70,7 +70,12 @@ next begins, so a plugin may rely on its dependencies being installed by
70
70
  the time its own `initialize` runs.
71
71
 
72
72
  If any phase throws, `manager.start` stops and disposes everything it had
73
- already brought up, then rethrows. `manager.stop` continues past a failing
73
+ already brought up, then rethrows. A disposed plugin cannot be brought back:
74
+ calling `manager.start` again after `manager.stop`, or after a rolled-back
75
+ startup, throws `PluginStateError` rather than silently starting nothing (or
76
+ starting still-registered dependents on top of disposed dependencies).
77
+ Unregister the disposed plugins and register fresh instances, or create a
78
+ new manager. `manager.stop` continues past a failing
74
79
  plugin so one bad `stop` cannot strand the rest; those failures are
75
80
  reported through the `onError` option (and logged to `console.error` if you
76
81
  do not supply one) rather than swallowed.
@@ -31,7 +31,11 @@ export class PluginDependencyVersionError extends PluginDependencyError {
31
31
  }
32
32
  }
33
33
  const SEMVER_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
34
- const RANGE_PATTERN = /^\s*(\^|~|>=|<=|>|<|=)?\s*(.+?)\s*$/;
34
+ // The input is already trimmed, so the outer `\s*` are unnecessary, and
35
+ // `(\S.*)` rather than `(.+?)\s*$`: `.` matches spaces too, so a lazy group
36
+ // followed by `\s*$` lets the engine split a whitespace run at every
37
+ // position before giving up.
38
+ const RANGE_PATTERN = /^(\^|~|>=|<=|>|<|=)?\s*(\S.*)$/;
35
39
  /**
36
40
  * Parses a semantic version, returning `undefined` if it is not one.
37
41
  */
@@ -63,7 +67,35 @@ export function compareVersions(a, b) {
63
67
  return 1;
64
68
  if (b.prerelease === undefined)
65
69
  return -1;
66
- return a.prerelease < b.prerelease ? -1 : 1;
70
+ return comparePrerelease(a.prerelease, b.prerelease);
71
+ }
72
+ /**
73
+ * Compares two prerelease strings identifier by identifier, as semver
74
+ * specifies: numeric identifiers compare numerically and rank below
75
+ * alphanumeric ones, and a longer identifier list ranks higher when the
76
+ * shared prefix is equal. A plain string comparison put `alpha.10`
77
+ * before `alpha.9`.
78
+ */
79
+ function comparePrerelease(a, b) {
80
+ const left = a.split(".");
81
+ const right = b.split(".");
82
+ const length = Math.min(left.length, right.length);
83
+ for (let index = 0; index < length; index += 1) {
84
+ const x = left[index];
85
+ const y = right[index];
86
+ if (x === y)
87
+ continue;
88
+ const xNumeric = /^\d+$/.test(x);
89
+ const yNumeric = /^\d+$/.test(y);
90
+ if (xNumeric && yNumeric)
91
+ return Number(x) - Number(y);
92
+ if (xNumeric)
93
+ return -1;
94
+ if (yNumeric)
95
+ return 1;
96
+ return x < y ? -1 : 1;
97
+ }
98
+ return left.length - right.length;
67
99
  }
68
100
  /**
69
101
  * Tests a version against a range.
@@ -2,7 +2,7 @@ import { PluginRegistryImpl } from "../pluginRegistry/pluginRegistry.core.js";
2
2
  import { DependencyResolver, assertResolutionValid, } from "../pluginDependencies/dependencyResolver.core.js";
3
3
  import { assertDependencyVersions } from "../pluginDependencies/versionCheck.core.js";
4
4
  import { LifecycleController } from "../pluginLifecycle/pluginLifecycle.core.js";
5
- import { PluginError, PluginRegistrationError } from "@zudojs/errors";
5
+ import { PluginError, PluginRegistrationError, PluginStateError, } from "@zudojs/errors";
6
6
  import { createOwnedPluginContext } from "../pluginIntegration/pluginContext.core.js";
7
7
  import { buildDiagnosticReport } from "../pluginDiagnostics/pluginDiagnostic.core.js";
8
8
  import { PLUGIN_EVENTS, createPluginLifecycleEvent, } from "../pluginEvents/pluginEvent.core.js";
@@ -124,10 +124,21 @@ export class PluginManager {
124
124
  assertDependencyVersions(this.plugins);
125
125
  }
126
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
+ }
127
138
  try {
128
139
  for (const name of this.startupOrder) {
129
140
  const registered = this.registry.get(name);
130
- if (!registered || registered.state === "disposed")
141
+ if (!registered)
131
142
  continue;
132
143
  // Guarded so a restart — where plugins are already installed
133
144
  // and merely stopped — re-runs only the phases it needs.
@@ -137,7 +148,7 @@ export class PluginManager {
137
148
  }
138
149
  for (const name of this.startupOrder) {
139
150
  const registered = this.registry.get(name);
140
- if (!registered || registered.state === "disposed")
151
+ if (!registered)
141
152
  continue;
142
153
  if (registered.state === "installed") {
143
154
  await this.lifecycle.initialize(registered, this.contextFor(registered, context));
@@ -145,7 +156,7 @@ export class PluginManager {
145
156
  }
146
157
  for (const name of this.startupOrder) {
147
158
  const registered = this.registry.get(name);
148
- if (!registered || registered.state === "disposed")
159
+ if (!registered)
149
160
  continue;
150
161
  if (registered.state === "initialized" ||
151
162
  registered.state === "stopped") {
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@zudojs/plugins",
3
- "version": "1.0.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",
@@ -20,8 +24,8 @@
20
24
  "!dist/.tsbuildinfo"
21
25
  ],
22
26
  "dependencies": {
23
- "@zudojs/errors": "1.0.0",
24
- "@zudojs/constants": "1.0.0",
27
+ "@zudojs/errors": "1.0.1",
28
+ "@zudojs/constants": "1.0.1",
25
29
  "@zudojs/types": "1.0.0"
26
30
  },
27
31
  "devDependencies": {