@scm-js/plugin-api 1.8.0 → 1.10.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 (2) hide show
  1. package/index.d.ts +95 -8
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -800,9 +800,21 @@ export interface IsomCheck {
800
800
  /** Rects whose tiles are not what their ISOM resolves to (doodad tiles are excused). */
801
801
  mismatched: number;
802
802
  }
803
- /** `checkIsom` with the verdict the palette and Check Map draw from it. */
803
+ /**
804
+ * `checkIsom` with what a rebuild would do about it — the verdict the palette, Check Map
805
+ * and the Repair plugin draw from.
806
+ *
807
+ * The two numbers measure opposite directions and are not inverses: `mismatched` is the
808
+ * lattice failing to reproduce the tiles, while a rebuild votes a lattice out of the
809
+ * tiles. A rebuild converges in one pass and leaves `inherent` behind for good, because
810
+ * hand-placed tiles, blends and another editor's ground are not terrain any lattice
811
+ * describes. Reporting `mismatched` alone therefore recommended a repair that could not
812
+ * move the number, on every map with terrain like that.
813
+ */
804
814
  export interface IsomReport extends IsomCheck {
805
- /** More than `STALE_ISOM_SHARE` of the rects disagree with their tiles. */
815
+ /** Of `mismatched`, the rects a rebuild would leave: terrain no lattice describes. */
816
+ inherent: number;
817
+ /** A rebuild would bring more than `STALE_ISOM_SHARE` of the rects back in step. */
806
818
  stale: boolean;
807
819
  }
808
820
  export interface LocationStringChange {
@@ -1663,6 +1675,13 @@ export interface HistoryEdit {
1663
1675
  * removes the section again rather than leaving an all-zero one behind.
1664
1676
  */
1665
1677
  createdIsom?: Uint16Array;
1678
+ /**
1679
+ * Set when the edit rebuilt an existing lattice from the tiles, which is the one edit
1680
+ * to `isom` the ISOM health is re-measured after: a brush stroke keeps the two in step
1681
+ * by construction and is deliberately not measured (`useIsomStatus`), and measuring
1682
+ * costs a second rebuild.
1683
+ */
1684
+ rebuiltIsom?: boolean;
1666
1685
  /** Unit placements, moves and deletions (see editor/units.ts). */
1667
1686
  units?: UnitChange[];
1668
1687
  /**
@@ -1791,7 +1810,20 @@ export interface Preferences {
1791
1810
  checkOnStart: boolean;
1792
1811
  nightly: boolean;
1793
1812
  };
1813
+ /**
1814
+ * What to do when an installed plugin has a newer release than the one running
1815
+ * (`plugins/updates.ts`). `notify` looks a few seconds after the plugins start and
1816
+ * raises a notice with a button to the rows offering the update; `manual` asks nothing
1817
+ * until **Check for update** is pressed on a row; `auto` installs what it finds, for the
1818
+ * plugins the user added — a default moves with the editor's own releases and is only
1819
+ * ever named in the notice. Every mode leaves the confirmation on a row's button alone.
1820
+ */
1821
+ plugins: {
1822
+ updates: PluginUpdateMode;
1823
+ };
1794
1824
  }
1825
+ /** See `Preferences.plugins.updates`. */
1826
+ export type PluginUpdateMode = "notify" | "manual" | "auto";
1795
1827
  /**
1796
1828
  * The version a host provides; a manifest that asks for a newer one is refused. It stays
1797
1829
  * at 1 while the API is only used by the plugins in the scm-js organisation and grows
@@ -1935,6 +1967,8 @@ export interface PluginApi {
1935
1967
  /** Key combinations, tried before the editor's own and never while a text field has focus. */
1936
1968
  readonly hotkeys: HotkeyApi;
1937
1969
  readonly commands: CommandsApi;
1970
+ /** Live objects one plugin holds out for others to use, found by name and watched for arriving. */
1971
+ readonly services: ServicesApi;
1938
1972
  readonly events: EventsApi;
1939
1973
  /**
1940
1974
  * A small key-value store of the plugin's own, kept in the browser's local storage under
@@ -2787,6 +2821,46 @@ export interface CommandsApi {
2787
2821
  /** Every command registered by every plugin. */
2788
2822
  list(): CommandInfo[];
2789
2823
  }
2824
+ export interface ServiceInfo {
2825
+ id: string;
2826
+ pluginId: string;
2827
+ version: number;
2828
+ }
2829
+ export interface ServiceOptions {
2830
+ /** The provider's version of the contract, 1 by default; a consumer that needs a newer one checks `ServiceInfo.version`. */
2831
+ version?: number;
2832
+ }
2833
+ /**
2834
+ * A command is one thing to do; a service is a thing to *hold* — an account another
2835
+ * plugin signs in through, a connection, a catalogue. A plugin provides one live object
2836
+ * under a name and every other plugin reaches it by that name, whatever order they were
2837
+ * activated in: `watch` answers at once with what is there and again whenever the
2838
+ * provider arrives or goes.
2839
+ *
2840
+ * The object's shape is the provider's to publish (a `contract.d.ts` in its repository,
2841
+ * taken as a dev dependency and imported with `import type`, which is erased before the
2842
+ * loader sees it); the editor never reads it. A name without a dot is namespaced under
2843
+ * the plugin (`"account"` → `"scmjs-dev.account"`); one with a dot is taken as it is.
2844
+ *
2845
+ * @example
2846
+ * // The provider:
2847
+ * api.services.provide("account", accountService);
2848
+ * // A consumer:
2849
+ * api.services.watch<AccountService>("scmjs-dev.account", (account) => {
2850
+ * if (account) useSessionFrom(account); else useOwnSignIn();
2851
+ * });
2852
+ */
2853
+ export interface ServicesApi {
2854
+ /** Hold an object out under a name. Providing the same name again replaces it; the Disposable withdraws it. */
2855
+ provide<T extends object>(id: string, service: T, options?: ServiceOptions): Disposable;
2856
+ /** The object under a name, or null when no plugin provides it. */
2857
+ get<T extends object>(id: string): T | null;
2858
+ has(id: string): boolean;
2859
+ /** Called at once with the current object (or null) and again on every change of provider. */
2860
+ watch<T extends object>(id: string, listener: (service: T | null, info: ServiceInfo | null) => void): Disposable;
2861
+ /** Every service provided by every plugin. */
2862
+ list(): ServiceInfo[];
2863
+ }
2790
2864
  /** A picture the editor already has: the canvas it draws from, and its size in pixels. */
2791
2865
  export interface PluginImage {
2792
2866
  image: HTMLCanvasElement;
@@ -3114,10 +3188,19 @@ export interface TerrainApi {
3114
3188
  /** Whether the open map carries an ISOM section the isometric brush can work on. */
3115
3189
  hasIsom(): boolean;
3116
3190
  /**
3117
- * How well the ISOM describes the tiles — `rects` measured, `mismatched` among them,
3118
- * and `stale` when the share is past what the palette warns at — or null when the map
3119
- * has no ISOM (`hasIsom`) or no map is open. Waits for the tileset graphics to load
3120
- * and rejects when they are missing.
3191
+ * How well the ISOM describes the tiles, and what rebuilding it would do about that:
3192
+ * `rects` measured, `mismatched` among them, `inherent` of those a rebuild would leave
3193
+ * behind (terrain no lattice describes — hand-placed tiles, blends, another editor's
3194
+ * ground), and `stale` when a rebuild would bring more than the palette's threshold
3195
+ * back in step. Null when the map has no ISOM (`hasIsom`) or no map is open. Waits for
3196
+ * the tileset graphics to load and rejects when they are missing.
3197
+ *
3198
+ * Offer `tx.rebuildIsom` on `stale`, not on `mismatched`: the two measure opposite
3199
+ * directions, a rebuild converges in one pass, and `inherent` never goes away.
3200
+ *
3201
+ * @example
3202
+ * const r = await api.terrain.checkIsom();
3203
+ * if (r?.stale) await api.document.edit("Rebuild ISOM", (tx) => { tx.rebuildIsom(); });
3121
3204
  */
3122
3205
  checkIsom(): Promise<IsomReport | null>;
3123
3206
  tileInfo(id: number): TileInfo | null;
@@ -4040,9 +4123,11 @@ export interface WidgetsApi {
4040
4123
  export type TopMenu = "File" | "Edit" | "View" | "Layer" | "Scenario" | "Triggers" | "Tools" | "Plugins" | "Help";
4041
4124
  /**
4042
4125
  * A top-level menu, or a submenu by label: `"File/Import"`. A last segment that names no
4043
- * submenu gets one of the plugin's own, at the end of the menu (`"Tools/AI"`).
4126
+ * submenu gets one of the plugin's own, at the end of the menu (`"Tools/AI"`), and a
4127
+ * first segment that names no top-level menu gets one made for the plugin, placed before
4128
+ * Help (`"Account"`).
4044
4129
  */
4045
- export type MenuPath = TopMenu | `${TopMenu}/${string}`;
4130
+ export type MenuPath = TopMenu | `${TopMenu}/${string}` | (string & {});
4046
4131
  export interface MenuItemSpec {
4047
4132
  label: string;
4048
4133
  /** Display only — bind the key with `hotkeys.add`. */
@@ -4146,6 +4231,8 @@ export type PluginEvent =
4146
4231
  | "file"
4147
4232
  /** A plugin registered or removed a command — how a plugin learns that one it calls by id has arrived. */
4148
4233
  | "commands"
4234
+ /** A plugin provided or withdrew a service — `services.watch` is the usual way to hear this for one name. */
4235
+ | "services"
4149
4236
  /** The game data source changed: installed, switched to another data set, or a copy removed. `gameData.source()` says what it is now. */
4150
4237
  | "gameData";
4151
4238
  /** Why the document changed. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scm-js/plugin-api",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Type declarations for the scmJS plugin API",
5
5
  "license": "MIT",
6
6
  "types": "index.d.ts",