lucid-extension-sdk 1.0.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 (60) hide show
  1. package/bin/constants.d.ts +14 -0
  2. package/bin/constants.js +2 -0
  3. package/bin/document/blockclasses/blockproxyregistry.d.ts +5 -0
  4. package/bin/document/blockclasses/blockproxyregistry.js +8 -0
  5. package/bin/document/blockclasses/erdblockproxy.d.ts +15 -0
  6. package/bin/document/blockclasses/erdblockproxy.js +40 -0
  7. package/bin/document/blockdefinition.d.ts +5 -0
  8. package/bin/document/blockdefinition.js +2 -0
  9. package/bin/document/blockproxy.d.ts +7 -0
  10. package/bin/document/blockproxy.js +17 -0
  11. package/bin/document/documentproxy.d.ts +10 -0
  12. package/bin/document/documentproxy.js +20 -0
  13. package/bin/document/elementproxy.d.ts +10 -0
  14. package/bin/document/elementproxy.js +30 -0
  15. package/bin/document/groupproxy.d.ts +9 -0
  16. package/bin/document/groupproxy.js +14 -0
  17. package/bin/document/itemproxy.d.ts +16 -0
  18. package/bin/document/itemproxy.js +54 -0
  19. package/bin/document/linedefinition.d.ts +29 -0
  20. package/bin/document/linedefinition.js +12 -0
  21. package/bin/document/lineproxy.d.ts +10 -0
  22. package/bin/document/lineproxy.js +40 -0
  23. package/bin/document/mapproxy.d.ts +16 -0
  24. package/bin/document/mapproxy.js +35 -0
  25. package/bin/document/pagedefinition.d.ts +3 -0
  26. package/bin/document/pagedefinition.js +2 -0
  27. package/bin/document/pageproxy.d.ts +20 -0
  28. package/bin/document/pageproxy.js +80 -0
  29. package/bin/editorclient.d.ts +21 -0
  30. package/bin/editorclient.js +100 -0
  31. package/bin/index.d.ts +4 -0
  32. package/bin/index.js +9 -0
  33. package/bin/math.d.ts +10 -0
  34. package/bin/math.js +2 -0
  35. package/bin/ui/menu.d.ts +26 -0
  36. package/bin/ui/menu.js +19 -0
  37. package/bin/ui/viewport.d.ts +10 -0
  38. package/bin/ui/viewport.js +22 -0
  39. package/package.json +13 -0
  40. package/src/constants.ts +14 -0
  41. package/src/document/blockclasses/blockproxyregistry.ts +12 -0
  42. package/src/document/blockclasses/erdblockproxy.ts +41 -0
  43. package/src/document/blockdefinition.ts +6 -0
  44. package/src/document/blockproxy.ts +17 -0
  45. package/src/document/documentproxy.ts +28 -0
  46. package/src/document/elementproxy.ts +41 -0
  47. package/src/document/groupproxy.ts +25 -0
  48. package/src/document/itemproxy.ts +58 -0
  49. package/src/document/linedefinition.ts +41 -0
  50. package/src/document/lineproxy.ts +48 -0
  51. package/src/document/mapproxy.ts +43 -0
  52. package/src/document/pagedefinition.ts +3 -0
  53. package/src/document/pageproxy.ts +128 -0
  54. package/src/editorclient.ts +109 -0
  55. package/src/index.ts +4 -0
  56. package/src/interop.d.ts +8 -0
  57. package/src/math.ts +2 -0
  58. package/src/ui/menu.ts +43 -0
  59. package/src/ui/viewport.ts +22 -0
  60. package/tsconfig.json +38 -0
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const blockproxy_1 = require("./document/blockproxy");
4
+ const documentproxy_1 = require("./document/documentproxy");
5
+ const elementproxy_1 = require("./document/elementproxy");
6
+ const groupproxy_1 = require("./document/groupproxy");
7
+ const lineproxy_1 = require("./document/lineproxy");
8
+ const pageproxy_1 = require("./document/pageproxy");
9
+ const blockproxyregistry_1 = require("./document/blockclasses/blockproxyregistry");
10
+ class EditorClient {
11
+ constructor() {
12
+ this.nextId = 0;
13
+ this.oneTimeCallbacks = new Map();
14
+ this.actions = new Map();
15
+ lucid.listen((msg) => {
16
+ var _a;
17
+ const resolver = this.oneTimeCallbacks.get(msg['id']);
18
+ if (resolver) {
19
+ resolver(msg['r']);
20
+ this.oneTimeCallbacks.delete(msg['id']);
21
+ }
22
+ else {
23
+ (_a = this.actions.get(msg['id'])) === null || _a === void 0 ? void 0 : _a(msg);
24
+ }
25
+ });
26
+ }
27
+ killExtension() {
28
+ this.sendCommand('k');
29
+ }
30
+ reloadExtension() {
31
+ this.sendCommand('r');
32
+ }
33
+ download(filename, data, mime, base64) {
34
+ this.sendCommand('d', {
35
+ 'f': filename,
36
+ 'd': data,
37
+ 'm': mime,
38
+ 'b64': base64,
39
+ });
40
+ }
41
+ showModal(title, width, height, content) {
42
+ this.sendCommand('sm', {
43
+ 't': title,
44
+ 'w': width,
45
+ 'h': height,
46
+ 'c': content,
47
+ });
48
+ }
49
+ hideModal() {
50
+ this.sendCommand('hm');
51
+ }
52
+ registerOneTimeAction(cb) {
53
+ const id = this.nextId++;
54
+ this.oneTimeCallbacks.set(id, cb);
55
+ return id;
56
+ }
57
+ registerAction(name, cb) {
58
+ this.actions.set(name, cb);
59
+ }
60
+ deleteAction(name) {
61
+ this.actions.delete(name);
62
+ }
63
+ actionExists(name) {
64
+ return this.actions.has(name);
65
+ }
66
+ sendCommand(name, params) {
67
+ return lucid.executeCommand(name, params);
68
+ }
69
+ getBlockProxy(id) {
70
+ const className = this.sendCommand('gp', { 'id': id, 'p': 'ClassName' });
71
+ const proxy = blockproxyregistry_1.findProxyClass(className);
72
+ if (proxy) {
73
+ return new proxy(id, this);
74
+ }
75
+ else {
76
+ return new blockproxy_1.BlockProxy(id, this);
77
+ }
78
+ }
79
+ loadBlockClasses(classNames) {
80
+ return this.sendCommand('lbc', classNames);
81
+ }
82
+ getElementProxy(id) {
83
+ const type = this.sendCommand('get', id);
84
+ switch (type) {
85
+ case 'block':
86
+ return this.getBlockProxy(id);
87
+ case 'line':
88
+ return new lineproxy_1.LineProxy(id, this);
89
+ case 'page':
90
+ return new pageproxy_1.PageProxy(id, this);
91
+ case 'document':
92
+ return new documentproxy_1.DocumentProxy(this);
93
+ case 'group':
94
+ return new groupproxy_1.GroupProxy(id, this);
95
+ default:
96
+ return new elementproxy_1.ElementProxy(id, this);
97
+ }
98
+ }
99
+ }
100
+ exports.EditorClient = EditorClient;
package/bin/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './editorclient';
2
+ export * from './document/documentproxy';
3
+ export * from './ui/menu';
4
+ export * from './ui/viewport';
package/bin/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ function __export(m) {
3
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4
+ }
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ __export(require("./editorclient"));
7
+ __export(require("./document/documentproxy"));
8
+ __export(require("./ui/menu"));
9
+ __export(require("./ui/viewport"));
package/bin/math.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export declare type Point = {
2
+ x: number;
3
+ y: number;
4
+ };
5
+ export declare type Box = {
6
+ x: number;
7
+ y: number;
8
+ w: number;
9
+ h: number;
10
+ };
package/bin/math.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,26 @@
1
+ import { EditorClient } from '../editorclient';
2
+ export declare const enum MenuType {
3
+ Main = 0,
4
+ Context = 1
5
+ }
6
+ export interface CustomMenuItem {
7
+ label: string;
8
+ action: string;
9
+ menuType: MenuType;
10
+ /**
11
+ * The standard menu item to display this item after.
12
+ * Examples:
13
+ * ['file'] -> put at the top of the File menu
14
+ * ['file', 'duplicate'] -> put after Duplicate in the File menu
15
+ * ['file', 'export'] -> put at the top of the export submenu
16
+ *
17
+ * The path is interpreted up to the first invalid entry.
18
+ * If the resulting valid path is empty, a new top-level menu named Add-ons appears before Help and this is added
19
+ */
20
+ path: string[];
21
+ }
22
+ export declare class Menu {
23
+ private readonly client;
24
+ constructor(client: EditorClient);
25
+ addMenuItem(item: CustomMenuItem): void;
26
+ }
package/bin/ui/menu.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Menu {
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ addMenuItem(item) {
8
+ if (!this.client.actionExists(item.action)) {
9
+ throw new Error('Unregistered action: ' + item.action);
10
+ }
11
+ this.client.sendCommand('ami', {
12
+ 'l': item.label,
13
+ 'a': item.action,
14
+ 't': item.menuType,
15
+ 'p': item.path,
16
+ });
17
+ }
18
+ }
19
+ exports.Menu = Menu;
@@ -0,0 +1,10 @@
1
+ import { ItemProxy } from '../document/itemproxy';
2
+ import { PageProxy } from '../document/pageproxy';
3
+ import { EditorClient } from '../editorclient';
4
+ export declare class Viewport {
5
+ private readonly client;
6
+ constructor(client: EditorClient);
7
+ getSelectedItems(): ItemProxy[];
8
+ getCurrentPage(): PageProxy;
9
+ setCurrentPage(page: PageProxy): void;
10
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const itemproxy_1 = require("../document/itemproxy");
4
+ const pageproxy_1 = require("../document/pageproxy");
5
+ class Viewport {
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ getSelectedItems() {
10
+ const ids = this.client.sendCommand('gs');
11
+ return ids
12
+ .map((id) => this.client.getElementProxy(id))
13
+ .filter((proxy) => proxy instanceof itemproxy_1.ItemProxy);
14
+ }
15
+ getCurrentPage() {
16
+ return new pageproxy_1.PageProxy(this.client.sendCommand('gcp'), this.client);
17
+ }
18
+ setCurrentPage(page) {
19
+ this.client.sendCommand('scp', page.id);
20
+ }
21
+ }
22
+ exports.Viewport = Viewport;
package/package.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "lucid-extension-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Utility classes for writing Lucid Software editor extensions",
5
+ "main": "bin/index.js",
6
+ "types": "bin/index.d.ts",
7
+ "author": "",
8
+ "license": "ISC",
9
+ "declaration": true,
10
+ "devDependencies": {
11
+ "@types/node": "^16.11.11"
12
+ }
13
+ }
@@ -0,0 +1,14 @@
1
+ export const enum OffsetType {
2
+ NW = 0,
3
+ NE = 1,
4
+ SE = 2,
5
+ SW = 3,
6
+ MOVE = 4,
7
+ ROTATE = 5,
8
+ SCALE = 6,
9
+ CUSTOM = 7,
10
+ N = 8,
11
+ E = 9,
12
+ S = 10,
13
+ W = 11,
14
+ }
@@ -0,0 +1,12 @@
1
+ import {BlockProxy} from '../blockproxy';
2
+ import {ERDBlockProxy} from './erdblockproxy';
3
+
4
+ export type BlockProxyConstructor = typeof BlockProxy & {
5
+ classNameRegex: RegExp;
6
+ };
7
+
8
+ const allProxyClasses: BlockProxyConstructor[] = [ERDBlockProxy];
9
+
10
+ export function findProxyClass(className: string): BlockProxyConstructor | undefined {
11
+ return allProxyClasses.find((proxy) => proxy.classNameRegex.test(className));
12
+ }
@@ -0,0 +1,41 @@
1
+ import {BlockProxy} from '../blockproxy';
2
+
3
+ export class ERDFieldProxy {
4
+ constructor(private readonly block: ERDBlockProxy, private readonly index: number) {}
5
+
6
+ public getName(): string {
7
+ return this.block.properties.get('Field' + this.index);
8
+ }
9
+
10
+ public getType(): string {
11
+ return this.block.properties.get('Type' + this.index) ?? '';
12
+ }
13
+
14
+ public getKey(): string {
15
+ return this.block.properties.get('Key' + this.index) ?? '';
16
+ }
17
+ }
18
+
19
+ export class ERDBlockProxy extends BlockProxy {
20
+ public static classNameRegex = /^ERDEntityBlock(2|3|4)?$/;
21
+
22
+ public getName(): string {
23
+ return this.properties.get('Name');
24
+ }
25
+
26
+ public getFieldCount(): number {
27
+ return this.properties.get('Fields');
28
+ }
29
+
30
+ public getFields() {
31
+ const fields: ERDFieldProxy[] = [];
32
+
33
+ const fieldCount = this.getFieldCount();
34
+ for (let i = 1; i <= fieldCount; i++) {
35
+ //These are 1-indexed in the property store
36
+ fields.push(new ERDFieldProxy(this, i));
37
+ }
38
+
39
+ return fields;
40
+ }
41
+ }
@@ -0,0 +1,6 @@
1
+ import {Box} from '../math';
2
+
3
+ export type BlockDefinition = {
4
+ className: string;
5
+ boundingBox: Box;
6
+ };
@@ -0,0 +1,17 @@
1
+ import {ItemProxy} from './itemproxy';
2
+ import {LineProxy} from './lineproxy';
3
+
4
+ export class BlockProxy extends ItemProxy {
5
+ public getClassName(): string {
6
+ return this.properties.get('ClassName');
7
+ }
8
+
9
+ public getRotation(): number {
10
+ return this.properties.get('Rotation');
11
+ }
12
+
13
+ public getConnectedLines() {
14
+ const ids: string[] = this.client.sendCommand('gcl', this.id);
15
+ return ids.map((id) => new LineProxy(id, this.client));
16
+ }
17
+ }
@@ -0,0 +1,28 @@
1
+ import {EditorClient} from '../editorclient';
2
+ import {ElementProxy} from './elementproxy';
3
+ import {MapProxy} from './mapproxy';
4
+ import {PageProxy} from './pageproxy';
5
+ import {PageDefinition} from './pagedefinition';
6
+
7
+ export class DocumentProxy extends ElementProxy {
8
+ public readonly pages = new MapProxy<string, PageProxy>(
9
+ this.client,
10
+ 'lp',
11
+ undefined,
12
+ (pageId) => new PageProxy(pageId, this.client),
13
+ );
14
+
15
+ constructor(client: EditorClient) {
16
+ super('', client);
17
+ }
18
+
19
+ public addPage(def: PageDefinition) {
20
+ const id = this.client.sendCommand('cp', {
21
+ 'Title': def.title,
22
+ });
23
+
24
+ const page = new PageProxy(id, this.client);
25
+ page.setTitle(def.title);
26
+ return page;
27
+ }
28
+ }
@@ -0,0 +1,41 @@
1
+ import {EditorClient} from '../editorclient';
2
+ import {MapProxy, WriteableMapProxy} from './mapproxy';
3
+
4
+ export class ElementProxy {
5
+ public readonly properties = new WriteableMapProxy<string, any>(
6
+ this.client,
7
+ 'lpr',
8
+ this.id,
9
+ (name) =>
10
+ this.client.sendCommand('gp', {
11
+ 'id': this.id,
12
+ 'p': name,
13
+ }),
14
+ (name, value) => {
15
+ if (name === 'BoundingBox') {
16
+ throw new Error(
17
+ 'Do not use properties.set() to move or resize items; use setLocation() or setBoundingBox() or offset()',
18
+ );
19
+ }
20
+
21
+ this.client.sendCommand('sp', {
22
+ 'id': this.id,
23
+ 'p': name,
24
+ 'v': value,
25
+ });
26
+ },
27
+ );
28
+
29
+ public readonly shapeData = new MapProxy<string, any>(this.client, 'lsd', this.id, (name) =>
30
+ this.client.sendCommand('gsd', {
31
+ 'id': this.id,
32
+ 'n': name,
33
+ }),
34
+ );
35
+
36
+ constructor(public readonly id: string, protected readonly client: EditorClient) {}
37
+
38
+ public exists(): boolean {
39
+ return this.client.sendCommand('ee', this.id);
40
+ }
41
+ }
@@ -0,0 +1,25 @@
1
+ import {ElementProxy} from './elementproxy';
2
+ import {MapProxy} from './mapproxy';
3
+ import {BlockProxy} from './blockproxy';
4
+ import {LineProxy} from './lineproxy';
5
+ import {ItemProxy} from './itemproxy';
6
+
7
+ export class GroupProxy extends ItemProxy {
8
+ public readonly blocks = new MapProxy<string, BlockProxy>(this.client, 'lb', this.id, (id) =>
9
+ this.client.getBlockProxy(id),
10
+ );
11
+
12
+ public readonly lines = new MapProxy<string, LineProxy>(
13
+ this.client,
14
+ 'll',
15
+ this.id,
16
+ (id) => new LineProxy(id, this.client),
17
+ );
18
+
19
+ public readonly groups = new MapProxy<string, GroupProxy>(
20
+ this.client,
21
+ 'lg',
22
+ this.id,
23
+ (id) => new GroupProxy(id, this.client),
24
+ );
25
+ }
@@ -0,0 +1,58 @@
1
+ import {ElementProxy} from './elementproxy';
2
+ import {MapProxy} from './mapproxy';
3
+ import {OffsetType} from '../constants';
4
+ import {Box, Point} from '../math';
5
+
6
+ export class ItemProxy extends ElementProxy {
7
+ public readonly textAreas = new MapProxy<string, string>(this.client, 'lta', this.id, (name) =>
8
+ this.client.sendCommand('gp', {
9
+ 'id': this.id,
10
+ 'p': name,
11
+ }),
12
+ );
13
+
14
+ public getBoundingBox() {
15
+ return this.properties.get('BoundingBox') as Box;
16
+ }
17
+
18
+ public setBoundingBox(bb: Box) {
19
+ const current = this.getBoundingBox();
20
+ if (current.w === bb.w && current.h === bb.h) {
21
+ //Move it into place
22
+ if (current.x !== bb.x || current.y !== bb.y) {
23
+ this.offset(OffsetType.MOVE, {x: bb.x - current.x, y: bb.y - current.y});
24
+ }
25
+ } else {
26
+ //Stretch it to size
27
+ if (current.x !== bb.x || current.y !== bb.y) {
28
+ this.offset(OffsetType.NW, {x: bb.x - current.x, y: bb.y - current.y});
29
+ }
30
+ if (current.x + current.w !== bb.x + bb.w || current.y + current.h !== bb.y + bb.h) {
31
+ this.offset(OffsetType.SE, {
32
+ x: bb.x + bb.w - (current.x + current.w),
33
+ y: bb.y + bb.h - (current.y + current.h),
34
+ });
35
+ }
36
+ }
37
+ }
38
+
39
+ public getLocation() {
40
+ const bb = this.getBoundingBox();
41
+ return {x: bb.x, y: bb.y};
42
+ }
43
+
44
+ public setLocation(location: Point) {
45
+ const current = this.getBoundingBox();
46
+ if (current.x !== location.x || current.y !== location.y) {
47
+ this.offset(OffsetType.MOVE, {x: location.x - current.x, y: location.y - current.y});
48
+ }
49
+ }
50
+
51
+ public offset(type: OffsetType, offset: Point) {
52
+ this.client.sendCommand('oi', {'ids': [this.id], 't': type, 'o': offset});
53
+ }
54
+
55
+ public delete() {
56
+ this.client.sendCommand('di', this.id);
57
+ }
58
+ }
@@ -0,0 +1,41 @@
1
+ import {BlockProxy} from './blockproxy';
2
+ import {LineProxy} from './lineproxy';
3
+
4
+ export interface EndpointStyle {
5
+ style?: string; //Omit to use defaults (theme)
6
+ }
7
+
8
+ export interface BlockEndpointDefinition extends EndpointStyle {
9
+ connection: BlockProxy;
10
+ linkX: number; //0 to 1, relative X position in target block's bounding box
11
+ linkY: number; //0 to 1, relative Y position in target block's bounding box
12
+ inside?: boolean;
13
+ autoLink?: boolean;
14
+ padding?: number;
15
+ }
16
+
17
+ export interface LineEndpointDefinition extends EndpointStyle {
18
+ connection: LineProxy;
19
+ position: number; //0 to 1, distance along the target line
20
+ }
21
+
22
+ export interface PositionEndpointDefinition extends EndpointStyle {
23
+ connection: void;
24
+ x: number;
25
+ y: number;
26
+ }
27
+
28
+ export type EndpointDefinition = BlockEndpointDefinition | LineEndpointDefinition | PositionEndpointDefinition;
29
+
30
+ export function isBlockEndpointDefinition(ep: EndpointDefinition): ep is BlockEndpointDefinition {
31
+ return ep.connection instanceof BlockProxy;
32
+ }
33
+
34
+ export function isLineEndpointDefinition(ep: EndpointDefinition): ep is LineEndpointDefinition {
35
+ return ep.connection instanceof LineProxy;
36
+ }
37
+
38
+ export type LineDefinition = {
39
+ endpoint1: EndpointDefinition;
40
+ endpoint2: EndpointDefinition;
41
+ };
@@ -0,0 +1,48 @@
1
+ import {Point} from '../math';
2
+ import {BlockProxy} from './blockproxy';
3
+ import {ElementProxy} from './elementproxy';
4
+ import {ItemProxy} from './itemproxy';
5
+
6
+ export class LineProxy extends ItemProxy {
7
+ private async getConnection(ep: {'Block'?: string; 'Line'?: string}) {
8
+ let proxy: ElementProxy | undefined;
9
+
10
+ if (ep['Block']) {
11
+ proxy = this.client.getBlockProxy(ep['Block']);
12
+ }
13
+ if (ep['Line']) {
14
+ proxy = new LineProxy(ep['Line'], this.client);
15
+ }
16
+
17
+ if (proxy && !proxy.exists()) {
18
+ return undefined;
19
+ }
20
+
21
+ return proxy;
22
+ }
23
+
24
+ public async getUpstreamConnection() {
25
+ const ep = this.properties.get('Endpoint1');
26
+ if (!(typeof ep === 'object')) {
27
+ return undefined;
28
+ }
29
+ return this.getConnection(ep);
30
+ }
31
+
32
+ public async getDownstreamConnection() {
33
+ const ep = this.properties.get('Endpoint2');
34
+ if (!(typeof ep === 'object')) {
35
+ return undefined;
36
+ }
37
+ return this.getConnection(ep);
38
+ }
39
+
40
+ public getConnectedLines() {
41
+ const ids: string[] = this.client.sendCommand('gcl', this.id);
42
+ return ids.map((id) => new LineProxy(id, this.client));
43
+ }
44
+
45
+ public getRelativePosition(relative: number): Point {
46
+ return this.client.sendCommand('grlp', {'id': this.id, 'p': relative});
47
+ }
48
+ }
@@ -0,0 +1,43 @@
1
+ import {EditorClient} from '../editorclient';
2
+
3
+ export class MapProxy<KEY, VALUE> {
4
+ constructor(
5
+ protected readonly client: EditorClient,
6
+ private readonly keyCommand: string,
7
+ private readonly keyParams: any,
8
+ private readonly getter: (key: KEY) => VALUE,
9
+ ) {}
10
+
11
+ public *[Symbol.iterator](): Iterator<[KEY, VALUE]> {
12
+ for (const key of this.keys()) {
13
+ const value = this.get(key);
14
+ if (value !== undefined) {
15
+ yield [key, value];
16
+ }
17
+ }
18
+ }
19
+
20
+ public keys(): KEY[] {
21
+ return this.client.sendCommand(this.keyCommand, this.keyParams);
22
+ }
23
+
24
+ public get(key: KEY) {
25
+ return this.getter(key);
26
+ }
27
+ }
28
+
29
+ export class WriteableMapProxy<KEY, VALUE> extends MapProxy<KEY, VALUE> {
30
+ constructor(
31
+ client: EditorClient,
32
+ keyCommand: string,
33
+ keyParams: any,
34
+ getter: (key: KEY) => VALUE,
35
+ private readonly setter: (key: KEY, val: VALUE) => void,
36
+ ) {
37
+ super(client, keyCommand, keyParams, getter);
38
+ }
39
+
40
+ public set(key: KEY, value: VALUE) {
41
+ this.setter(key, value);
42
+ }
43
+ }
@@ -0,0 +1,3 @@
1
+ export type PageDefinition = {
2
+ title: string;
3
+ };