@appsoftwareltd/etherpk-extension-api 0.12.0 → 0.14.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.
@@ -35,8 +35,6 @@ export interface ViewDeclaration {
35
35
  /**
36
36
  * The View lives in a Sidebar from the moment a graph opens, beside the Client's own residents,
37
37
  * and the Sidebar's toggle brings it back if it was closed. `desktopOnly` keeps it off a phone.
38
- *
39
- * @beta
40
38
  */
41
39
  resident?: {
42
40
  side: 'left' | 'right';
@@ -132,7 +130,7 @@ export interface ExtensionManifest {
132
130
  * An extension's package as the Client reads it: the standard package.json fields it uses and the
133
131
  * manifest.
134
132
  *
135
- * @beta
133
+ * @public
136
134
  */
137
135
  export interface ExtensionPackage {
138
136
  /** The npm package name. */
@@ -149,7 +147,7 @@ export interface ExtensionPackage {
149
147
  /**
150
148
  * The answer of {@link readExtensionPackage}: the package, or every way its manifest is wrong.
151
149
  *
152
- * @beta
150
+ * @public
153
151
  */
154
152
  export type ReadExtensionPackageResult = {
155
153
  ok: true;
@@ -164,6 +162,6 @@ export type ReadExtensionPackageResult = {
164
162
  * Checks what the Client depends on: names it uses as keys, paths it resolves, and declarations
165
163
  * it registers before any of the extension's code runs. It does not check that files exist.
166
164
  *
167
- * @beta
165
+ * @public
168
166
  */
169
167
  export declare function readExtensionPackage(packageJson: unknown): ReadExtensionPackageResult;
package/dist/manifest.js CHANGED
@@ -14,7 +14,7 @@ const ICON_MARKUP_LIMIT = 4096;
14
14
  * Checks what the Client depends on: names it uses as keys, paths it resolves, and declarations
15
15
  * it registers before any of the extension's code runs. It does not check that files exist.
16
16
  *
17
- * @beta
17
+ * @public
18
18
  */
19
19
  export function readExtensionPackage(packageJson) {
20
20
  const errors = [];
package/dist/menus.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * A document, reached from its tab, a Favourite, Recents or an All Documents row.
7
7
  *
8
- * @beta
8
+ * @public
9
9
  */
10
10
  export interface DocumentMenuTarget {
11
11
  /** Where the menu was raised: the document's tab, or a row naming it. */
@@ -20,7 +20,7 @@ export interface DocumentMenuTarget {
20
20
  /**
21
21
  * A tab that is not a document's.
22
22
  *
23
- * @beta
23
+ * @public
24
24
  */
25
25
  export interface TabMenuTarget {
26
26
  /** Any tab that is not a document's. */
@@ -33,7 +33,7 @@ export interface TabMenuTarget {
33
33
  /**
34
34
  * A wikilink in an editor.
35
35
  *
36
- * @beta
36
+ * @public
37
37
  */
38
38
  export interface WikilinkMenuTarget {
39
39
  /** A wikilink in an editor. */
@@ -47,7 +47,7 @@ export interface WikilinkMenuTarget {
47
47
  * A thing an extension raises a menu on, of a kind the extension names under its own id
48
48
  * (`kanban.card`). Only rows that check for that kind apply to it.
49
49
  *
50
- * @beta
50
+ * @public
51
51
  */
52
52
  export interface ExtensionMenuTarget {
53
53
  /** `<extension id>.<name>`. */
@@ -58,15 +58,16 @@ export interface ExtensionMenuTarget {
58
58
  /**
59
59
  * What a Context Menu can be raised on that an extension may add rows to. The Client also raises
60
60
  * menus on things this list does not name, an Asset or a misspelt word, so a row's `when` answers
61
- * false for any kind it does not check for.
61
+ * false for any kind it does not check for. Kinds are only ever added to the list: when the Client
62
+ * no longer raises a menu on one, its rows are simply not shown.
62
63
  *
63
- * @beta
64
+ * @public
64
65
  */
65
66
  export type MenuTarget = DocumentMenuTarget | TabMenuTarget | WikilinkMenuTarget | ExtensionMenuTarget;
66
67
  /**
67
68
  * One Context Menu row.
68
69
  *
69
- * @beta
70
+ * @public
70
71
  */
71
72
  export interface ContextMenuItem {
72
73
  /** Under the extension's id: `graph-view.showConcept`. */
@@ -81,6 +82,8 @@ export interface ContextMenuItem {
81
82
  icon?: string;
82
83
  /** A separator above the row. */
83
84
  separatorBefore?: boolean | ((target: MenuTarget) => boolean);
85
+ /** The row deletes or removes something for good, so it is drawn in the danger colour, as the Client's own Delete rows are. */
86
+ danger?: boolean;
84
87
  /** Whether the row applies to a target. Absent means every target. */
85
88
  when?: (target: MenuTarget) => boolean;
86
89
  }
@@ -94,8 +97,6 @@ export interface CommandMenuContext {
94
97
  inTable: boolean;
95
98
  /**
96
99
  * A table may be inserted at the caret.
97
- *
98
- * @beta
99
100
  */
100
101
  tableInsertable: boolean;
101
102
  /** The document's body may be written: false in a locked Protected Document. */
@@ -110,8 +111,6 @@ export interface CommandMenuContext {
110
111
  * caret line's links, the links above it in the outline, the document's own concept, then the
111
112
  * scopes in its name. Names are as written, an alias as the alias. Worked out only when a row
112
113
  * reads it. Absent reads as none.
113
- *
114
- * @beta
115
114
  */
116
115
  readonly conceptsAtCaret?: readonly string[];
117
116
  }
@@ -144,11 +143,33 @@ export interface CommandMenuItem {
144
143
  command: string;
145
144
  /**
146
145
  * What the Command is given.
147
- *
148
- * @beta
149
146
  */
150
147
  args?: unknown;
151
148
  }
149
+ /**
150
+ * A button on the Command Bar, the row of buttons across the bottom of a phone's screen. Pressing
151
+ * it runs `command` and leaves the keyboard where it was, so a Command can tell whether the caret
152
+ * is in the document.
153
+ *
154
+ * @public
155
+ */
156
+ export interface CommandBarButton {
157
+ /** Under the extension's id. */
158
+ id: string;
159
+ /** The button's name, said to a screen reader and shown as its tooltip: the bar shows icons only. */
160
+ title: string;
161
+ /** Its icon: the extension's own or one of the Client's. */
162
+ icon: string;
163
+ /**
164
+ * In the bar's pinned group at its right end, which never scrolls away, rather than after the
165
+ * editing buttons that scroll. For an action a person reaches for often.
166
+ */
167
+ pinned?: boolean;
168
+ /** The Command the button runs. */
169
+ command: string;
170
+ /** What the Command is given. */
171
+ args?: unknown;
172
+ }
152
173
  /**
153
174
  * A button in the Graph Sidebar's group of action buttons, after Search and today's date: a way in
154
175
  * to what the extension shows for the whole graph, such as the Graph Map. Pressing it runs
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Records an extension keeps on this device for the open graph alone (ADR 0147): never synced,
3
+ * never seen by another device or another member, and deleted when the graph's data is removed
4
+ * from the device. For what is the person's work on this device, such as a chat they have not
5
+ * saved, rather than a preference that should follow them (`personStorage`).
6
+ */
7
+ /**
8
+ * The extension's records for the open graph on this device.
9
+ *
10
+ * Each record is stored as the browser's structured clone of the value, so it may hold a `Blob`,
11
+ * an `ArrayBuffer`, a `Date` or plain data, but no function. A record holds at most 4 MB: its text
12
+ * and the bytes of every `Blob` and buffer in it. A larger one is refused. Records live in the browser's
13
+ * IndexedDB, which a private window or a full disk may refuse: a refused write rejects, and a
14
+ * refused read answers as if there were nothing.
15
+ *
16
+ * @public
17
+ */
18
+ export interface ExtensionGraphRecords {
19
+ /** The record under `key`, or undefined when there is none. */
20
+ get<T>(key: string): Promise<T | undefined>;
21
+ /**
22
+ * Keep a record under `key`: letters, digits, `.`, `_`, `:` and `-`, at most 200 of them.
23
+ * Rejects when the key is not one of those, the record is over 4 MB, or the browser refuses
24
+ * the write (a full disk, a private window).
25
+ */
26
+ set(key: string, value: unknown): Promise<void>;
27
+ /** Remove the record under `key`. */
28
+ remove(key: string): Promise<void>;
29
+ /** The keys of every record the extension keeps for the open graph, sorted. */
30
+ keys(): Promise<string[]>;
31
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Records an extension keeps on this device for the open graph alone (ADR 0147): never synced,
3
+ * never seen by another device or another member, and deleted when the graph's data is removed
4
+ * from the device. For what is the person's work on this device, such as a chat they have not
5
+ * saved, rather than a preference that should follow them (`personStorage`).
6
+ */
7
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * An extension's own section in the Client's settings (ADR 0134, amended 2026-10-15 and
3
+ * 2026-10-17), for settings that belong to the person and need more than the fields a manifest
4
+ * can declare, such as a list of accounts with a button that connects one. The main module exports
5
+ * them as `settingsSections`.
6
+ *
7
+ * The Client draws an extension's sections in a graph's Settings and Extensions while the extension
8
+ * runs there. An extension that comes with EtherPK is loaded with the Client, so its sections are
9
+ * drawn on the Graphs page too, with no graph open. Any other extension's code is loaded only once
10
+ * a graph opens, so its sections are not drawn on the Graphs page.
11
+ */
12
+ import type { ExtensionAuth } from './auth';
13
+ import type { ExtensionPersonStorage, ExtensionSettings, ExtensionTheme } from './context';
14
+ /**
15
+ * Where an extension's settings section is drawn: `extension`, under the extension's own entry in
16
+ * the Extensions area, beside the settings its manifest declares; or `agents`, in the Agents tab.
17
+ *
18
+ * @public
19
+ */
20
+ export type SettingsSectionTab = 'extension' | 'agents';
21
+ /**
22
+ * What a settings section is mounted with: what belongs to the person, and nothing from a graph,
23
+ * since there may be no graph open.
24
+ *
25
+ * @public
26
+ */
27
+ export interface SettingsSectionContext {
28
+ /** The extension's id, from its manifest. */
29
+ readonly extensionId: string;
30
+ /** The person's answers to the settings the manifest declares. */
31
+ readonly settings: ExtensionSettings;
32
+ /** The extension's records kept with the person. */
33
+ readonly personStorage: ExtensionPersonStorage;
34
+ /** Signing in to another service. */
35
+ readonly auth: ExtensionAuth;
36
+ /** The Client's light or dark theme. */
37
+ readonly theme: ExtensionTheme;
38
+ /** Say something in passing, as the Client's own notices do. */
39
+ notify(text: string): void;
40
+ }
41
+ /**
42
+ * A section the section's host element shows, as the Client drives it.
43
+ *
44
+ * @public
45
+ */
46
+ export interface MountedSettingsSection {
47
+ /** The tab closed, or the extension was switched off. */
48
+ destroy(): void;
49
+ }
50
+ /**
51
+ * One settings section an extension adds.
52
+ *
53
+ * @public
54
+ */
55
+ export interface SettingsSection {
56
+ /** Unique within the extension. */
57
+ id: string;
58
+ /** The tab it goes in. */
59
+ tab: SettingsSectionTab;
60
+ /** Draw the section into `element`, which is empty and is the extension's alone. */
61
+ mount(element: HTMLElement, context: SettingsSectionContext): MountedSettingsSection;
62
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsoftwareltd/etherpk-extension-api",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "license": "MIT",
5
5
  "description": "The API an EtherPK extension is written against: the context it is started with, its manifest, and the contract its Views follow.",
6
6
  "type": "module",
@@ -9,13 +9,15 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "default": "./dist/index.js"
12
- }
12
+ },
13
+ "./controls.css": "./controls.css"
13
14
  },
14
15
  "publishConfig": {
15
16
  "access": "public"
16
17
  },
17
18
  "files": [
18
19
  "dist",
20
+ "controls.css",
19
21
  "LICENSE",
20
22
  "README.md"
21
23
  ],