@yam8d/m8-sdk 0.1.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 ADDED
@@ -0,0 +1,44 @@
1
+ # @yam8d/m8-sdk
2
+
3
+ Client SDK for iframe applications that communicate with an M8 host.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @yam8d/m8-sdk
9
+ ```
10
+
11
+ For local development before the package is published:
12
+
13
+ ```bash
14
+ npm install ../yam8d/packages/m8-sdk
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```ts
20
+ import { createM8Client } from '@yam8d/m8-sdk'
21
+
22
+ const m8 = await createM8Client()
23
+
24
+ console.log(m8.state.viewName)
25
+ await m8.sendKeyPress(['play'])
26
+
27
+ const unsubscribe = m8.onStateChange((state) => {
28
+ console.log(state.cursorPos)
29
+ })
30
+
31
+ unsubscribe()
32
+ m8.disconnect()
33
+ ```
34
+
35
+ For React or other environments where top-level `await` is not convenient:
36
+
37
+ ```ts
38
+ import { createM8ClientSync } from '@yam8d/m8-sdk'
39
+
40
+ const { client, connect } = createM8ClientSync()
41
+ await connect()
42
+ ```
43
+
44
+ The app must run inside the host iframe. Opening it directly in a standalone browser tab cannot establish the SDK handshake.
package/dist/index.js ADDED
@@ -0,0 +1,162 @@
1
+ import { ChildHandshake as e, DebugMessenger as t, WindowMessenger as n } from "post-me";
2
+ //#region src/client.ts
3
+ var r = () => ({
4
+ viewName: null,
5
+ viewTitle: null,
6
+ minimapKey: null,
7
+ cursorPos: null,
8
+ cursorRect: null,
9
+ selectionMode: !1,
10
+ highlightColor: null,
11
+ titleColor: null,
12
+ backgroundColor: null,
13
+ textUnderCursor: null,
14
+ currentLine: null,
15
+ deviceModel: null,
16
+ fontMode: null,
17
+ systemInfo: null,
18
+ macroRunning: !1
19
+ }), i = class {
20
+ constructor(e = {}) {
21
+ this.connection = null, this.remoteHandle = null, this.localHandle = null, this.stateCallbacks = /* @__PURE__ */ new Set(), this.viewCallbacks = /* @__PURE__ */ new Set(), this.cursorCallbacks = /* @__PURE__ */ new Set(), this.textCallbacks = /* @__PURE__ */ new Set(), this.keyCallbacks = /* @__PURE__ */ new Set(), this._state = r(), this._isConnected = !1, this.config = e;
22
+ }
23
+ get state() {
24
+ return this._state;
25
+ }
26
+ get isConnected() {
27
+ return this._isConnected;
28
+ }
29
+ async connect() {
30
+ if (this.connection) return;
31
+ let r = new n({
32
+ localWindow: window,
33
+ remoteWindow: window.parent,
34
+ remoteOrigin: "*"
35
+ });
36
+ this.config.debug && (r = t(r, (e, ...t) => {
37
+ console.log("[M8 SDK]", e, ...t);
38
+ }));
39
+ let i = await e(r, { ping: async () => "pong" });
40
+ this.connection = i, this.remoteHandle = i.remoteHandle(), this.localHandle = i.localHandle(), this._isConnected = !0, this.remoteHandle.addEventListener("stateChanged", (e) => {
41
+ this._state = e, this.stateCallbacks.forEach((t) => {
42
+ t(e);
43
+ });
44
+ }), this.remoteHandle.addEventListener("viewChanged", ({ viewName: e, viewTitle: t }) => {
45
+ this._state = {
46
+ ...this._state,
47
+ viewName: e,
48
+ viewTitle: t
49
+ }, this.viewCallbacks.forEach((n) => {
50
+ n(e, t);
51
+ });
52
+ }), this.remoteHandle.addEventListener("cursorMoved", ({ pos: e, rect: t, selectionMode: n }) => {
53
+ this._state = {
54
+ ...this._state,
55
+ cursorPos: e,
56
+ cursorRect: t,
57
+ selectionMode: n
58
+ }, this.cursorCallbacks.forEach((r) => {
59
+ r(e, t, n);
60
+ });
61
+ }), this.remoteHandle.addEventListener("textUpdated", ({ textUnderCursor: e, currentLine: t }) => {
62
+ this._state = {
63
+ ...this._state,
64
+ textUnderCursor: e,
65
+ currentLine: t
66
+ }, this.textCallbacks.forEach((n) => {
67
+ n(e, t);
68
+ });
69
+ }), this.remoteHandle.addEventListener("keyPressed", ({ keys: e }) => {
70
+ this.keyCallbacks.forEach((t) => {
71
+ t(e);
72
+ });
73
+ }), await this.fetchState(), this.localHandle.emit("ready", void 0);
74
+ }
75
+ async navigateToView(e) {
76
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
77
+ return this.remoteHandle.call("navigateToView", e);
78
+ }
79
+ async navigateTo(e, t) {
80
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
81
+ return this.remoteHandle.call("navigateTo", e, t);
82
+ }
83
+ async setValueToHex(e) {
84
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
85
+ return this.remoteHandle.call("setValueToHex", e);
86
+ }
87
+ async setValueToInt(e) {
88
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
89
+ return this.remoteHandle.call("setValueToInt", e);
90
+ }
91
+ async setNote(e) {
92
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
93
+ return this.remoteHandle.call("setNote", e);
94
+ }
95
+ async setValueToString(e, t = !0, n = !1) {
96
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
97
+ return this.remoteHandle.call("setValueToString", e, t, n);
98
+ }
99
+ async browseFile(e, t = !0) {
100
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
101
+ return this.remoteHandle.call("browseFile", e, t);
102
+ }
103
+ async sendKeyPress(e) {
104
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
105
+ return this.remoteHandle.call("sendKeyPress", e);
106
+ }
107
+ async sendKeyDown(e) {
108
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
109
+ return this.remoteHandle.call("sendKeyDown", e);
110
+ }
111
+ async sendKeyUp() {
112
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
113
+ return this.remoteHandle.call("sendKeyUp");
114
+ }
115
+ getState() {
116
+ return this._state;
117
+ }
118
+ async fetchState() {
119
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
120
+ let e = await this.remoteHandle.call("getState");
121
+ return this._state = e, e;
122
+ }
123
+ onStateChange(e) {
124
+ return this.stateCallbacks.add(e), () => this.stateCallbacks.delete(e);
125
+ }
126
+ onViewChange(e) {
127
+ return this.viewCallbacks.add(e), () => this.viewCallbacks.delete(e);
128
+ }
129
+ onCursorMove(e) {
130
+ return this.cursorCallbacks.add(e), () => this.cursorCallbacks.delete(e);
131
+ }
132
+ onTextUpdate(e) {
133
+ return this.textCallbacks.add(e), () => this.textCallbacks.delete(e);
134
+ }
135
+ onKeyPress(e) {
136
+ return this.keyCallbacks.add(e), () => this.keyCallbacks.delete(e);
137
+ }
138
+ disconnect() {
139
+ this.connection?.close(), this.connection = null, this.remoteHandle = null, this.localHandle = null, this._isConnected = !1, this.stateCallbacks.clear(), this.viewCallbacks.clear(), this.cursorCallbacks.clear(), this.textCallbacks.clear(), this.keyCallbacks.clear();
140
+ }
141
+ };
142
+ async function a(e = {}) {
143
+ let t = new i(e);
144
+ return await t.connect(), t;
145
+ }
146
+ function o(e = {}) {
147
+ let t = new i(e);
148
+ return {
149
+ client: t,
150
+ connect: async () => {
151
+ await t.connect();
152
+ }
153
+ };
154
+ }
155
+ var s = {
156
+ createM8Client: a,
157
+ createM8ClientSync: o
158
+ };
159
+ //#endregion
160
+ export { a as createM8Client, o as createM8ClientSync, s as default };
161
+
162
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["// @ts-expect-error - post-me types are incomplete for the generic handshake signatures used here.\nimport { ChildHandshake, DebugMessenger, WindowMessenger } from 'post-me'\n// @ts-expect-error - post-me types are incomplete for the generic handshake signatures used here.\nimport type { Connection, LocalHandle, RemoteHandle } from 'post-me'\nimport type { M8ClientEvents, M8ClientMethods, M8HostEvents, M8HostMethods, M8KeyName, M8SdkConfig, M8State } from './types'\n\nexport type { CursorPos, CursorRect, M8KeyName, M8State, RGB, SystemInfos } from './types'\n\nexport interface M8Client {\n readonly state: M8State\n readonly isConnected: boolean\n navigateToView(viewName: string): Promise<boolean>\n navigateTo(x: number, y: number): Promise<void>\n setValueToHex(targetHex: number): Promise<boolean>\n setValueToInt(targetInt: number): Promise<boolean>\n setNote(noteString: string): Promise<boolean>\n setValueToString(targetString: string, exact?: boolean, searchInCurrentLine?: boolean): Promise<boolean>\n browseFile(targetText: string, exact?: boolean): Promise<boolean>\n sendKeyPress(keys: M8KeyName[]): Promise<void>\n sendKeyDown(keys: M8KeyName[]): Promise<void>\n sendKeyUp(): Promise<void>\n getState(): M8State\n fetchState(): Promise<M8State>\n onStateChange(callback: (state: M8State) => void): () => void\n onViewChange(callback: (viewName: string | null, viewTitle: string | null) => void): () => void\n onCursorMove(callback: (pos: M8State['cursorPos'], rect: M8State['cursorRect'], selectionMode: boolean) => void): () => void\n onTextUpdate(callback: (textUnderCursor: string | null, currentLine: string | null) => void): () => void\n onKeyPress(callback: (keys: number) => void): () => void\n disconnect(): void\n}\n\nconst getDefaultState = (): M8State => ({\n viewName: null,\n viewTitle: null,\n minimapKey: null,\n cursorPos: null,\n cursorRect: null,\n selectionMode: false,\n highlightColor: null,\n titleColor: null,\n backgroundColor: null,\n textUnderCursor: null,\n currentLine: null,\n deviceModel: null,\n fontMode: null,\n systemInfo: null,\n macroRunning: false,\n})\n\nclass M8ClientImpl implements M8Client {\n private connection: Connection<M8ClientMethods, M8HostEvents, M8HostMethods, M8ClientEvents> | null = null\n private remoteHandle: RemoteHandle<M8HostMethods, M8HostEvents> | null = null\n private localHandle: LocalHandle<M8ClientMethods, M8ClientEvents> | null = null\n private readonly stateCallbacks = new Set<(state: M8State) => void>()\n private readonly viewCallbacks = new Set<(viewName: string | null, viewTitle: string | null) => void>()\n private readonly cursorCallbacks = new Set<(pos: M8State['cursorPos'], rect: M8State['cursorRect'], selectionMode: boolean) => void>()\n private readonly textCallbacks = new Set<(textUnderCursor: string | null, currentLine: string | null) => void>()\n private readonly keyCallbacks = new Set<(keys: number) => void>()\n private _state: M8State = getDefaultState()\n private _isConnected = false\n private readonly config: M8SdkConfig\n\n constructor(config: M8SdkConfig = {}) {\n this.config = config\n }\n\n get state(): M8State {\n return this._state\n }\n\n get isConnected(): boolean {\n return this._isConnected\n }\n\n async connect(): Promise<void> {\n if (this.connection) {\n return\n }\n\n let messenger = new WindowMessenger({\n localWindow: window,\n remoteWindow: window.parent,\n remoteOrigin: '*',\n })\n\n if (this.config.debug) {\n messenger = DebugMessenger(messenger, (msg: string, ...args: unknown[]) => {\n console.log('[M8 SDK]', msg, ...args)\n })\n }\n\n const connection = await ChildHandshake<M8ClientMethods, M8HostEvents, M8HostMethods, M8ClientEvents>(messenger, {\n ping: async () => 'pong',\n })\n\n this.connection = connection\n this.remoteHandle = connection.remoteHandle()\n this.localHandle = connection.localHandle()\n this._isConnected = true\n\n this.remoteHandle.addEventListener('stateChanged', (state: M8State) => {\n this._state = state\n this.stateCallbacks.forEach((cb) => {\n cb(state)\n })\n })\n\n this.remoteHandle.addEventListener('viewChanged', ({ viewName, viewTitle }: { viewName: string | null; viewTitle: string | null }) => {\n this._state = { ...this._state, viewName, viewTitle }\n this.viewCallbacks.forEach((cb) => {\n cb(viewName, viewTitle)\n })\n })\n\n this.remoteHandle.addEventListener('cursorMoved', ({ pos, rect, selectionMode }: { pos: M8State['cursorPos']; rect: M8State['cursorRect']; selectionMode: boolean }) => {\n this._state = { ...this._state, cursorPos: pos, cursorRect: rect, selectionMode }\n this.cursorCallbacks.forEach((cb) => {\n cb(pos, rect, selectionMode)\n })\n })\n\n this.remoteHandle.addEventListener('textUpdated', ({ textUnderCursor, currentLine }: { textUnderCursor: string | null; currentLine: string | null }) => {\n this._state = { ...this._state, textUnderCursor, currentLine }\n this.textCallbacks.forEach((cb) => {\n cb(textUnderCursor, currentLine)\n })\n })\n\n this.remoteHandle.addEventListener('keyPressed', ({ keys }: { keys: number }) => {\n this.keyCallbacks.forEach((cb) => {\n cb(keys)\n })\n })\n\n await this.fetchState()\n this.localHandle.emit('ready', undefined)\n }\n\n async navigateToView(viewName: string): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('navigateToView', viewName)\n }\n\n async navigateTo(x: number, y: number): Promise<void> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('navigateTo', x, y)\n }\n\n async setValueToHex(targetHex: number): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('setValueToHex', targetHex)\n }\n\n async setValueToInt(targetInt: number): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('setValueToInt', targetInt)\n }\n\n async setNote(noteString: string): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('setNote', noteString)\n }\n\n async setValueToString(targetString: string, exact = true, searchInCurrentLine = false): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('setValueToString', targetString, exact, searchInCurrentLine)\n }\n\n async browseFile(targetText: string, exact = true): Promise<boolean> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('browseFile', targetText, exact)\n }\n\n async sendKeyPress(keys: M8KeyName[]): Promise<void> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('sendKeyPress', keys)\n }\n\n async sendKeyDown(keys: M8KeyName[]): Promise<void> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('sendKeyDown', keys)\n }\n\n async sendKeyUp(): Promise<void> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n return this.remoteHandle.call('sendKeyUp')\n }\n\n getState(): M8State {\n return this._state\n }\n\n async fetchState(): Promise<M8State> {\n if (!this.remoteHandle) throw new Error('M8 SDK client is not connected')\n const state = await this.remoteHandle.call('getState')\n this._state = state\n return state\n }\n\n onStateChange(callback: (state: M8State) => void): () => void {\n this.stateCallbacks.add(callback)\n return () => this.stateCallbacks.delete(callback)\n }\n\n onViewChange(callback: (viewName: string | null, viewTitle: string | null) => void): () => void {\n this.viewCallbacks.add(callback)\n return () => this.viewCallbacks.delete(callback)\n }\n\n onCursorMove(callback: (pos: M8State['cursorPos'], rect: M8State['cursorRect'], selectionMode: boolean) => void): () => void {\n this.cursorCallbacks.add(callback)\n return () => this.cursorCallbacks.delete(callback)\n }\n\n onTextUpdate(callback: (textUnderCursor: string | null, currentLine: string | null) => void): () => void {\n this.textCallbacks.add(callback)\n return () => this.textCallbacks.delete(callback)\n }\n\n onKeyPress(callback: (keys: number) => void): () => void {\n this.keyCallbacks.add(callback)\n return () => this.keyCallbacks.delete(callback)\n }\n\n disconnect(): void {\n this.connection?.close()\n this.connection = null\n this.remoteHandle = null\n this.localHandle = null\n this._isConnected = false\n this.stateCallbacks.clear()\n this.viewCallbacks.clear()\n this.cursorCallbacks.clear()\n this.textCallbacks.clear()\n this.keyCallbacks.clear()\n }\n}\n\nexport async function createM8Client(config: M8SdkConfig = {}): Promise<M8Client> {\n const client = new M8ClientImpl(config)\n await client.connect()\n return client\n}\n\nexport function createM8ClientSync(config: M8SdkConfig = {}): { client: M8Client; connect: () => Promise<void> } {\n const client = new M8ClientImpl(config)\n return {\n client,\n connect: async () => {\n await client.connect()\n },\n }\n}\n\nexport default {\n createM8Client,\n createM8ClientSync,\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@yam8d/m8-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Client SDK for iframe applications that communicate with an M8 host.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./types/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "types",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "vite build",
22
+ "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
23
+ "prepack": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "m8",
27
+ "sdk",
28
+ "iframe",
29
+ "postmessage"
30
+ ],
31
+ "license": "MIT",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "dependencies": {
36
+ "post-me": "^0.4.5"
37
+ },
38
+ "devDependencies": {
39
+ "typescript": "~5.9.3",
40
+ "vite": "^8.0.1"
41
+ }
42
+ }
@@ -0,0 +1,115 @@
1
+ export interface CursorPos {
2
+ x: number
3
+ y: number
4
+ }
5
+
6
+ export interface CursorRect {
7
+ x: number
8
+ y: number
9
+ w: number
10
+ h: number
11
+ }
12
+
13
+ export interface RGB {
14
+ r: number
15
+ g: number
16
+ b: number
17
+ }
18
+
19
+ export interface SystemInfos {
20
+ [key: string]: string | number | boolean | undefined
21
+ }
22
+
23
+ export interface M8State {
24
+ viewName: string | null
25
+ viewTitle: string | null
26
+ minimapKey: string | null
27
+ cursorPos: CursorPos | null
28
+ cursorRect: CursorRect | null
29
+ selectionMode: boolean
30
+ highlightColor: RGB | null
31
+ titleColor: RGB | null
32
+ backgroundColor: RGB | null
33
+ textUnderCursor: string | null
34
+ currentLine: string | null
35
+ deviceModel: string | null
36
+ fontMode: number | null
37
+ systemInfo: SystemInfos | null
38
+ macroRunning: boolean
39
+ macroCurrentStep?: number
40
+ macroSequenceLength?: number
41
+ }
42
+
43
+ export type M8KeyName = 'left' | 'right' | 'up' | 'down' | 'shift' | 'play' | 'opt' | 'edit'
44
+
45
+ export interface M8HostMethods {
46
+ navigateToView(viewName: string): Promise<boolean>
47
+ navigateTo(x: number, y: number): Promise<void>
48
+ setValueToHex(targetHex: number): Promise<boolean>
49
+ setValueToInt(targetInt: number): Promise<boolean>
50
+ setNote(noteString: string): Promise<boolean>
51
+ setValueToString(targetString: string, exact?: boolean, searchInCurrentLine?: boolean): Promise<boolean>
52
+ browseFile(targetText: string, exact?: boolean): Promise<boolean>
53
+ sendKeyPress(keys: M8KeyName[]): Promise<void>
54
+ sendKeyDown(keys: M8KeyName[]): Promise<void>
55
+ sendKeyUp(): Promise<void>
56
+ getState(): Promise<M8State>
57
+ }
58
+
59
+ export interface M8ClientMethods {
60
+ ping(): Promise<string>
61
+ }
62
+
63
+ export interface M8HostEvents {
64
+ stateChanged: M8State
65
+ viewChanged: { viewName: string | null; viewTitle: string | null }
66
+ cursorMoved: { pos: CursorPos | null; rect: CursorRect | null; selectionMode: boolean }
67
+ textUpdated: { textUnderCursor: string | null; currentLine: string | null }
68
+ keyPressed: { keys: number }
69
+ }
70
+
71
+ export interface M8ClientEvents {
72
+ ready: undefined
73
+ error: { message: string }
74
+ }
75
+
76
+ export interface M8SdkConfig {
77
+ debug?: boolean
78
+ }
79
+
80
+ export interface M8Client {
81
+ readonly state: M8State
82
+ readonly isConnected: boolean
83
+ navigateToView(viewName: string): Promise<boolean>
84
+ navigateTo(x: number, y: number): Promise<void>
85
+ setValueToHex(targetHex: number): Promise<boolean>
86
+ setValueToInt(targetInt: number): Promise<boolean>
87
+ setNote(noteString: string): Promise<boolean>
88
+ setValueToString(targetString: string, exact?: boolean, searchInCurrentLine?: boolean): Promise<boolean>
89
+ browseFile(targetText: string, exact?: boolean): Promise<boolean>
90
+ sendKeyPress(keys: M8KeyName[]): Promise<void>
91
+ sendKeyDown(keys: M8KeyName[]): Promise<void>
92
+ sendKeyUp(): Promise<void>
93
+ getState(): M8State
94
+ fetchState(): Promise<M8State>
95
+ onStateChange(callback: (state: M8State) => void): () => void
96
+ onViewChange(callback: (viewName: string | null, viewTitle: string | null) => void): () => void
97
+ onCursorMove(callback: (pos: M8State['cursorPos'], rect: M8State['cursorRect'], selectionMode: boolean) => void): () => void
98
+ onTextUpdate(callback: (textUnderCursor: string | null, currentLine: string | null) => void): () => void
99
+ onKeyPress(callback: (keys: number) => void): () => void
100
+ disconnect(): void
101
+ }
102
+
103
+ export function createM8Client(config?: M8SdkConfig): Promise<M8Client>
104
+
105
+ export function createM8ClientSync(config?: M8SdkConfig): {
106
+ client: M8Client
107
+ connect: () => Promise<void>
108
+ }
109
+
110
+ declare const m8Sdk: {
111
+ createM8Client: typeof createM8Client
112
+ createM8ClientSync: typeof createM8ClientSync
113
+ }
114
+
115
+ export default m8Sdk