@forumone/throughline-plugin-contract 0.4.1 → 0.5.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
@@ -6,11 +6,29 @@ Shared type contracts every Throughline core plugin satisfies, plus the cross-pl
6
6
 
7
7
  - `CorePlugin<Options>` — the Payload plugin signature every core package exports
8
8
  - `BaseCorePluginOptions` — options every plugin accepts (`enabled`, `logger`, and `routePrefix` for a plugin that serves HTTP endpoints of its own)
9
+ - `CollectionPluginOptions`, `PluginAdminOptions`, `DEFAULT_ADMIN_GROUP`, `resolveAdminGroup` — the `admin: { group }` option every plugin that declares a collection accepts, its `'Throughline'` default, and the helper that turns it into a collection's `admin.group` (see below)
9
10
  - `McpToolDefinition`, `McpToolContext`, `McpMeta` — the MCP tool surface
10
11
  - `AuthenticatedUser` — the actor a tool handler receives
12
+ - `EnvRequirement` — `{ name, minLength?, why }`: one environment variable a plugin cannot start without, as data. A plugin exports a list of them as `<plugin>Env` (`approvalsEnv`), and a site passes the lists to `assertEnvironment` from `@forumone/throughline-core`
11
13
  - `getPluginRegistry` — the runtime registry plugins use to announce themselves and check for sibling plugins
12
14
  - `examplePlugin` — a reference implementation showing the exact shape every future plugin follows
13
15
 
16
+ ## Admin group for plugin-owned collections
17
+
18
+ A plugin that declares a collection extends `CollectionPluginOptions` and spreads `resolveAdminGroup(options.admin)` into each collection's `admin` block:
19
+
20
+ ```ts
21
+ admin: { ...resolveAdminGroup(options.admin), useAsTitle: 'title' }
22
+ ```
23
+
24
+ | `admin.group` | Result |
25
+ | --- | --- |
26
+ | omitted | the `'Throughline'` group (`DEFAULT_ADMIN_GROUP`) |
27
+ | `'Workflow'` (or `{ en: 'Workflow', fr: 'Flux' }`) | that group |
28
+ | `false` | ungrouped — Payload's default "Collections" section |
29
+
30
+ `false` here means *ungrouped*. On a collection's own `admin.group`, Payload reads `false` as "leave out of the nav entirely"; `resolveAdminGroup` never passes `false` through.
31
+
14
32
  ## Authoring a plugin
15
33
 
16
34
  See `docs/building-plugins.md` at the repo root.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Where a plugin-owned collection sits in the admin sidebar.
3
+ *
4
+ * A string (or a map of locale to string, as Payload accepts) names the
5
+ * group. `false` leaves the collection ungrouped, in Payload's default
6
+ * "Collections" section — which is not what `false` means on a collection's
7
+ * own `admin.group`: there Payload reads it as "leave out of the nav
8
+ * entirely". A plugin translates this value; it never passes `false` through.
9
+ */
10
+ export type PluginAdminGroup = string | Record<string, string> | false;
11
+ /**
12
+ * Admin options accepted by every Throughline plugin that declares a
13
+ * collection. Plugins that declare none do not accept it, for the same reason
14
+ * a plugin with no endpoints omits `routePrefix`: an option it cannot honour
15
+ * would be a silent no-op.
16
+ */
17
+ export interface PluginAdminOptions {
18
+ /**
19
+ * Sidebar group for every collection the plugin declares. Defaults to
20
+ * {@link DEFAULT_ADMIN_GROUP}. `false` leaves them ungrouped.
21
+ *
22
+ * Payload renders an ungrouped collection loose at the top of the sidebar,
23
+ * above every group — which is why the default is a group and not nothing.
24
+ */
25
+ group?: PluginAdminGroup;
26
+ }
27
+ /**
28
+ * The options a collection-declaring plugin adds to its own. Kept apart from
29
+ * `BaseCorePluginOptions` so that only those plugins carry it.
30
+ */
31
+ export interface CollectionPluginOptions {
32
+ /** Admin UI placement for the collections this plugin declares. */
33
+ admin?: PluginAdminOptions;
34
+ }
35
+ /** The sidebar group plugin-owned collections land in when no group is given. */
36
+ export declare const DEFAULT_ADMIN_GROUP = "Throughline";
37
+ /**
38
+ * Resolves a plugin's `admin` option to the fragment it spreads into each
39
+ * collection's `admin` block: `{ group }` for a named group, `{}` for
40
+ * ungrouped. Never returns `group: false`, which Payload would read as hidden.
41
+ */
42
+ export declare function resolveAdminGroup(admin?: PluginAdminOptions): {
43
+ group?: string | Record<string, string>;
44
+ };
45
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,KAAK,CAAC,EAAE,kBAAkB,CAAA;CAC3B;AAED,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAEhD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG;IAC7D,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxC,CAGA"}
package/dist/admin.js ADDED
@@ -0,0 +1,12 @@
1
+ /** The sidebar group plugin-owned collections land in when no group is given. */
2
+ export const DEFAULT_ADMIN_GROUP = 'Throughline';
3
+ /**
4
+ * Resolves a plugin's `admin` option to the fragment it spreads into each
5
+ * collection's `admin` block: `{ group }` for a named group, `{}` for
6
+ * ungrouped. Never returns `group: false`, which Payload would read as hidden.
7
+ */
8
+ export function resolveAdminGroup(admin) {
9
+ const group = admin?.group ?? DEFAULT_ADMIN_GROUP;
10
+ return group === false ? {} : { group };
11
+ }
12
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAqCA,iFAAiF;AACjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAA;AAEhD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA0B;IAG1D,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,mBAAmB,CAAA;IACjD,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAA;AACzC,CAAC"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * One environment variable something needs before it can start, as data.
3
+ *
4
+ * A plugin that falls back to `process.env` at init exports a list of these
5
+ * beside its factory — `approvalsPlugin` / `approvalsEnv`, `emailPlugin` /
6
+ * `emailEnv` — and its own init check reads the same entries. A site hands
7
+ * every list, plus its own variables, to `assertEnvironment` from
8
+ * `@forumone/throughline-core`, which reports everything wrong in one error
9
+ * before any plugin gets to throw on the first thing it finds.
10
+ *
11
+ * It describes the *environment fallback*. A site that passes the value as an
12
+ * option instead (say `tokenSecret` from a secrets manager) leaves that
13
+ * plugin's list out of its `assertEnvironment` call.
14
+ */
15
+ export interface EnvRequirement {
16
+ /** The variable's name, e.g. `APPROVAL_TOKEN_SECRET`. */
17
+ readonly name: string;
18
+ /**
19
+ * The shortest value accepted. For secrets that sign or key something,
20
+ * where a short value is as bad as none.
21
+ */
22
+ readonly minLength?: number;
23
+ /**
24
+ * Why it is needed and how to get one, in a sentence a person fixing a
25
+ * deploy can act on. Printed beside the name; never include a value.
26
+ */
27
+ readonly why: string;
28
+ }
29
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB"}
package/dist/env.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -32,6 +32,8 @@ export interface Logger {
32
32
  * returns a standard Payload {@link Plugin}.
33
33
  */
34
34
  export type CorePlugin<Options extends BaseCorePluginOptions = BaseCorePluginOptions> = (options: Options) => Plugin;
35
+ export * from './admin.js';
36
+ export * from './env.js';
35
37
  export * from './mcp.js';
36
38
  export * from './registry.js';
37
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,4FAA4F;IAC5F,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CACpE;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,SAAS,qBAAqB,GAAG,qBAAqB,IAAI,CACtF,OAAO,EAAE,OAAO,KACb,MAAM,CAAA;AAEX,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,4FAA4F;IAC5F,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CACpE;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,SAAS,qBAAqB,GAAG,qBAAqB,IAAI,CACtF,OAAO,EAAE,OAAO,KACb,MAAM,CAAA;AAEX,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ export * from './admin.js';
2
+ export * from './env.js';
1
3
  export * from './mcp.js';
2
4
  export * from './registry.js';
3
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwCA,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwCA,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-plugin-contract",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Shared plugin and MCP contract types and the cross-plugin registry for @forumone/throughline core packages.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,12 +25,12 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "payload": "^3.0.0",
28
+ "payload": "^3.89.0",
29
29
  "zod": "^3.23.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^24.13.2",
33
- "eslint": "^9.15.0",
33
+ "eslint": "^10.11.0",
34
34
  "typescript": "^5.6.0",
35
35
  "@forumone/throughline-eslint-config": "0.0.0",
36
36
  "@forumone/throughline-tsconfig": "0.0.0"