@tagma/sdk 0.3.7 → 0.3.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tagma/sdk",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
package/src/registry.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type {
2
2
  PluginCategory, DriverPlugin, TriggerPlugin,
3
- CompletionPlugin, MiddlewarePlugin,
3
+ CompletionPlugin, MiddlewarePlugin, PluginManifest,
4
4
  } from './types';
5
5
 
6
6
  type PluginType = DriverPlugin | TriggerPlugin | CompletionPlugin | MiddlewarePlugin;
@@ -155,6 +155,41 @@ export function isValidPluginName(name: unknown): name is string {
155
155
  return typeof name === 'string' && PLUGIN_NAME_RE.test(name);
156
156
  }
157
157
 
158
+ /**
159
+ * Parse and validate the `tagmaPlugin` field of a `package.json` blob.
160
+ *
161
+ * Returns the strongly-typed manifest if the field is present and
162
+ * well-formed (`category` is one of the four known categories and `type`
163
+ * is a non-empty string). Returns `null` if the field is absent — that
164
+ * is the host's signal that the package is a library, not a plugin.
165
+ *
166
+ * Throws if the field is present but malformed: that's a packaging bug
167
+ * the plugin author should hear about loudly, not a silent skip.
168
+ *
169
+ * Hosts use this during auto-discovery to decide whether to load a
170
+ * package as a plugin without having to dynamically `import()` it.
171
+ */
172
+ export function readPluginManifest(pkgJson: unknown): PluginManifest | null {
173
+ if (!pkgJson || typeof pkgJson !== 'object') return null;
174
+ const raw = (pkgJson as Record<string, unknown>).tagmaPlugin;
175
+ if (raw === undefined) return null;
176
+ if (!raw || typeof raw !== 'object') {
177
+ throw new Error('tagmaPlugin field must be an object with { category, type }');
178
+ }
179
+ const m = raw as Record<string, unknown>;
180
+ const category = m.category;
181
+ const type = m.type;
182
+ if (typeof category !== 'string' || !VALID_CATEGORIES.has(category as PluginCategory)) {
183
+ throw new Error(
184
+ `tagmaPlugin.category must be one of ${[...VALID_CATEGORIES].join(', ')}, got ${JSON.stringify(category)}`
185
+ );
186
+ }
187
+ if (typeof type !== 'string' || type.length === 0) {
188
+ throw new Error(`tagmaPlugin.type must be a non-empty string, got ${JSON.stringify(type)}`);
189
+ }
190
+ return { category: category as PluginCategory, type };
191
+ }
192
+
158
193
  export async function loadPlugins(pluginNames: readonly string[]): Promise<void> {
159
194
  for (const name of pluginNames) {
160
195
  if (!isValidPluginName(name)) {
package/src/sdk.ts CHANGED
@@ -51,6 +51,7 @@ export {
51
51
  listRegistered,
52
52
  isValidPluginName,
53
53
  PLUGIN_NAME_RE,
54
+ readPluginManifest,
54
55
  } from './registry';
55
56
  export type { RegisterResult } from './registry';
56
57