@micro-lc/preview 0.5.0-rc4 → 0.5.0-rc6

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## Unreleased
2
2
 
3
+ ### Added
4
+
5
+ - standalone service-worker that might act as a reverse proxy when employed
6
+ - e2e tests run with TLS (both local and CI pipeline)
7
+
3
8
  ### Versioning
4
9
 
5
10
  - `rxjs` bumped to version `v7.8.1`
package/dist/index.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  import type { Manifest } from '@micro-lc/back-kit-engine/schemas';
2
2
  import type { Component, PluginConfiguration } from '@micro-lc/interfaces/schemas/v2';
3
+ interface UrlMatchPair {
4
+ headers: Record<string, string>;
5
+ originalFrom: `${string}/`;
6
+ query: Record<string, string>;
7
+ to: `${string}/`;
8
+ }
9
+ type SourceMapItems = Record<`${string}/`, UrlMatchPair>;
3
10
  interface TagInfo {
4
11
  definitions?: Record<string, unknown>;
5
12
  description?: string;
@@ -24,6 +31,7 @@ interface OptionMessage {
24
31
  content: {
25
32
  disableOverlay?: boolean;
26
33
  redirectTo?: string;
34
+ run?: boolean;
27
35
  timeout?: number;
28
36
  };
29
37
  type: 'options';
@@ -39,19 +47,21 @@ type RegisteredElementMessages = {
39
47
  content: StyledElementContent | undefined;
40
48
  type: 'focus-element';
41
49
  };
50
+ interface NewConfiguration {
51
+ configuration: PluginConfiguration;
52
+ contexts: Map<string, Component[]>;
53
+ tags: string[];
54
+ }
42
55
  interface NewConfigurationMessage {
43
- content: {
44
- configuration: PluginConfiguration;
45
- contexts: Map<string, Component[]>;
46
- tags: string[];
47
- };
56
+ content: NewConfiguration;
48
57
  type: 'new-configuration';
49
58
  }
59
+ interface UpdateConfiguration {
60
+ configuration: PluginConfiguration;
61
+ context: Component;
62
+ }
50
63
  interface UpdateConfigurationMessage {
51
- content: {
52
- configuration: PluginConfiguration;
53
- context: Component;
54
- };
64
+ content: UpdateConfiguration;
55
65
  type: 'update';
56
66
  }
57
67
  interface UpdatedMessage {
@@ -60,24 +70,10 @@ interface UpdatedMessage {
60
70
  }
61
71
  type RegisteredConfigMessages = NewConfigurationMessage | UpdateConfigurationMessage;
62
72
  type ReducedMouseEvent = Pick<MouseEvent, 'bubbles' | 'cancelable' | 'clientX' | 'clientY'>;
63
- interface ServiceWorkerConfig {
64
- dictionary: Record<`${string}/`, {
65
- headers: Record<string, string>;
66
- query: Record<string, string>;
67
- to: `${string}/`;
68
- }>;
69
- scope?: string;
70
- }
71
73
  interface SourceMapMessage {
72
- content: ServiceWorkerConfig;
74
+ content: SourceMapItems;
73
75
  type: 'set-source-map';
74
76
  }
75
- interface ServiceWorkerMessage {
76
- content: {
77
- status: 'ready';
78
- };
79
- type: 'service-worker';
80
- }
81
77
  type RegisteredMessages = {
82
78
  content: ReducedMouseEvent;
83
79
  type: 'mousedown' | 'mousemove';
@@ -92,7 +88,7 @@ type RegisteredMessages = {
92
88
  } | {
93
89
  content: InfoEntry[];
94
90
  type: 'tag-info';
95
- } | RegisteredConfigMessages | UpdatedMessage | RegisteredElementMessages | OptionMessage | RequestResource | SourceMapMessage | ServiceWorkerMessage;
91
+ } | RegisteredConfigMessages | UpdatedMessage | RegisteredElementMessages | OptionMessage | RequestResource | SourceMapMessage;
96
92
  interface NotifyProps extends Record<string, unknown> {
97
93
  data?: Record<string, string>;
98
94
  description: string;
@@ -115,21 +111,6 @@ declare const MIA_PREVIEW_ID = "__mia_preview_id";
115
111
  declare const OVERLAY_Z_INDEX = 1000000;
116
112
  declare const DEFAULT_MODE = "select";
117
113
  declare function isRegisteredMessage(input: unknown): input is RegisteredMessages;
118
- declare const generateDarkColorHex: () => string;
119
- declare class PostChannel {
120
- private __instance;
121
- private __handler;
122
- private __window;
123
- private __randomColor;
124
- private postMessage;
125
- constructor(handler: (this: PostChannel, message: RegisteredMessages) => void);
126
- set instance(str: string);
127
- get window(): Window;
128
- set window(win: Window);
129
- send(to: Window, message: RegisteredMessages, origin?: string): void;
130
- recv(window: Window, from?: Window | null): () => void;
131
- }
132
- export type { OverlayMode, TagInfo, InfoEntry, ElementContent, StyledElementContent, NewConfigurationMessage, UpdateConfigurationMessage, RegisteredConfigMessages, RegisteredMessages, OptionMessage, NotifyProps, Reset, Update, RequestResource, SourceMapMessage, ServiceWorkerConfig, };
133
- export type * from './service-worker';
134
- export { MIA_PREVIEW_ID, OVERLAY_Z_INDEX, DEFAULT_MODE, generateDarkColorHex, isRegisteredMessage, PostChannel, };
114
+ export type { NewConfiguration, UpdateConfiguration, OverlayMode, TagInfo, InfoEntry, ElementContent, StyledElementContent, NewConfigurationMessage, UpdateConfigurationMessage, RegisteredConfigMessages, RegisteredMessages, OptionMessage, NotifyProps, Reset, Update, RequestResource, SourceMapItems, UrlMatchPair, };
115
+ export { MIA_PREVIEW_ID, OVERLAY_Z_INDEX, DEFAULT_MODE, isRegisteredMessage, };
135
116
  export * from './handlebars';
package/dist/index.js CHANGED
@@ -7,20 +7,19 @@ const MIA_PREVIEW_ID = '__mia_preview_id';
7
7
  const OVERLAY_Z_INDEX = 1_000_000;
8
8
  const DEFAULT_MODE = 'select';
9
9
  const keys = {
10
- 'click-element': DebugMessage.Skip,
11
- 'ctrl-space': DebugMessage.Skip,
10
+ 'click-element': DebugMessage.Default,
11
+ 'ctrl-space': DebugMessage.Default,
12
12
  'focus-element': DebugMessage.Default,
13
- mousedown: DebugMessage.Skip,
13
+ mousedown: DebugMessage.Default,
14
14
  mousemove: DebugMessage.Skip,
15
15
  'new-configuration': DebugMessage.Default,
16
- notification: DebugMessage.Skip,
17
- options: DebugMessage.Skip,
18
- 'request-resource': DebugMessage.Skip,
19
- 'service-worker': DebugMessage.Skip,
16
+ notification: DebugMessage.Default,
17
+ options: DebugMessage.Default,
18
+ 'request-resource': DebugMessage.Default,
20
19
  'set-source-map': DebugMessage.Default,
21
- 'tag-info': DebugMessage.Skip,
22
- update: DebugMessage.Skip,
23
- updated: DebugMessage.Skip,
20
+ 'tag-info': DebugMessage.Default,
21
+ update: DebugMessage.Default,
22
+ updated: DebugMessage.Default,
24
23
  };
25
24
  const isValidKey = (type) => Object.keys(keys).includes(type);
26
25
  function isRegisteredMessage(input) {
@@ -35,91 +34,5 @@ function isRegisteredMessage(input) {
35
34
  }
36
35
  return true;
37
36
  }
38
- function isInstanceMessage(input, signature) {
39
- if (input === null) {
40
- return false;
41
- }
42
- if (typeof input !== 'object') {
43
- return false;
44
- }
45
- if (!('type' in input) || typeof input.type !== 'string') {
46
- return false;
47
- }
48
- const { type: signedType } = input;
49
- if (!signedType.startsWith(signature)) {
50
- return false;
51
- }
52
- const type = signedType.substring(signature.length);
53
- if (!isValidKey(type)) {
54
- return false;
55
- }
56
- return true;
57
- }
58
- const sign = (signature, message) => ({ ...message, type: `${signature}${message.type}` });
59
- const unsign = (signature, message) => {
60
- let { type } = message;
61
- if (type.startsWith(signature)) {
62
- type = type.substring(signature.length);
63
- }
64
- return { ...message, type };
65
- };
66
- const generateDarkColorHex = () => {
67
- let color = '#';
68
- for (let i = 0; i < 3; i++) {
69
- color += (`0${Math.floor(Math.random() * Math.pow(16, 2) / 2).toString(16)}`).slice(-2);
70
- }
71
- return color;
72
- };
73
- class PostChannel {
74
- __instance;
75
- __handler;
76
- __window;
77
- __randomColor;
78
- postMessage(to, message, origin) {
79
- if (import.meta.env.MODE !== 'production' || this.__window.__BACKOFFICE_CONFIGURATOR_LOG_LEVEL__ === 'debug') {
80
- console.assert(to !== this.__window);
81
- }
82
- if ( /* (import.meta.env.MODE !== 'production' || this.__window.__BACKOFFICE_CONFIGURATOR_LOG_LEVEL__ === 'debug') && */keys[message.type] !== DebugMessage.Skip) {
83
- const color = this.__randomColor;
84
- const background = `${color}22`;
85
- const style = { background, color };
86
- const hasTop = this.__window.top !== this.__window;
87
- console.groupCollapsed(`%c Msg from ${this.__window.origin} ${hasTop ? '(inner)' : '(top)'} `, Object.entries(style).map(([key, val]) => `${key}: ${val}`).join('; '));
88
- console.info(`window '${this.__window.origin}' is sending a message of type %c ${message.type} `, 'background: lightgreen; color: darkgreen');
89
- console.log('to', to);
90
- console.log(message.content);
91
- console.groupEnd();
92
- }
93
- to.postMessage(sign(this.__instance, message), origin);
94
- }
95
- constructor(handler) {
96
- this.__instance = '';
97
- this.__handler = handler;
98
- this.__window = window;
99
- this.__randomColor = generateDarkColorHex();
100
- }
101
- set instance(str) {
102
- this.__instance = str;
103
- }
104
- get window() {
105
- return this.__window;
106
- }
107
- set window(win) {
108
- this.__window = win;
109
- }
110
- send(to, message, origin = '*') {
111
- this.__window !== to && this.postMessage(to, message, origin);
112
- }
113
- recv(window, from = null) {
114
- const listener = ({ data, source }) => {
115
- if ((from === null || source === from) && isInstanceMessage(data, this.__instance)) {
116
- const message = unsign(this.__instance, data);
117
- this.__handler(message);
118
- }
119
- };
120
- window.addEventListener('message', listener);
121
- return () => window.removeEventListener('message', listener);
122
- }
123
- }
124
- export { MIA_PREVIEW_ID, OVERLAY_Z_INDEX, DEFAULT_MODE, generateDarkColorHex, isRegisteredMessage, PostChannel, };
37
+ export { MIA_PREVIEW_ID, OVERLAY_Z_INDEX, DEFAULT_MODE, isRegisteredMessage, };
125
38
  export * from './handlebars';
@@ -1,28 +1,16 @@
1
+ /// <reference lib="webworker" />
1
2
  interface UrlMatchPair {
2
3
  headers: Record<string, string>;
3
4
  originalFrom: `${string}/`;
4
5
  query: Record<string, string>;
5
6
  to: `${string}/`;
6
7
  }
7
- interface SourceMapItems {
8
- dictionary: Record<`${string}/`, UrlMatchPair>;
9
- scope?: string;
10
- }
11
- type WorkerMessage = {
8
+ type SourceMapItems = Record<`${string}/`, UrlMatchPair>;
9
+ type IncomingWorkerMessage = {
12
10
  content: SourceMapItems;
13
11
  type: 'set-source-map';
14
- } | {
15
- content: {
16
- clientId: string;
17
- };
18
- type: 'source-map-ack';
19
- } | {
20
- content: {
21
- status: 'ready';
22
- };
23
- type: 'service-worker';
24
12
  } | {
25
13
  content: Record<string, never>;
26
14
  type: 'unload-client';
27
15
  };
28
- export type { SourceMapItems, UrlMatchPair, WorkerMessage, };
16
+ export type { IncomingWorkerMessage, SourceMapItems, UrlMatchPair, };
@@ -1 +1,146 @@
1
- export {};
1
+ import PostChannel, { fromServiceWorkerToReceiver } from '@micro-lc/post-channel';
2
+ import { ReplaySubject } from 'rxjs';
3
+ // every sw client opens a dedicated channel
4
+ // this map collects, per client, a buffer and the communication channel itself
5
+ const openChannels = new Map();
6
+ // source maps can be stored by unique
7
+ // key which is either the scope or the clientId
8
+ const sourceMap = new Map();
9
+ // reverse map
10
+ const tosMap = new Map();
11
+ const isAvailable = (key, map) => {
12
+ const iter = map.keys();
13
+ let matchingKey;
14
+ let { done = false, value } = iter.next();
15
+ while (!done && matchingKey === undefined) {
16
+ if (value !== undefined && key.startsWith(value)) {
17
+ matchingKey = value;
18
+ done = true;
19
+ }
20
+ const { value: nextValue, done: nextDone = false } = iter.next();
21
+ done = nextDone;
22
+ value = nextValue;
23
+ }
24
+ return matchingKey;
25
+ };
26
+ const isWindowClient = (source) => source !== null && 'id' in source;
27
+ const errorCatcher = (clientId) => (error) => console.error(`[SW]: error on ${clientId} - ${String(error)}`);
28
+ const getReceiver = fromServiceWorkerToReceiver(self, { errorCatcher });
29
+ const makeListener = (clientId) => {
30
+ return function listener({ data }) {
31
+ // todo: missing validation
32
+ const workerMessageData = data;
33
+ switch (workerMessageData.type) {
34
+ case 'set-source-map': {
35
+ const { content } = workerMessageData;
36
+ const clientMaps = Object.entries(content).reduce((maps, [key, value]) => {
37
+ const { clientSourceMap, clientTosMap } = maps;
38
+ if (Object.keys(value.headers).length > 0) {
39
+ clientTosMap.set(encodeURI(value.to), value.headers);
40
+ }
41
+ clientSourceMap.set(encodeURI(key), value);
42
+ return maps;
43
+ }, { clientSourceMap: new Map(), clientTosMap: new Map() });
44
+ sourceMap.set(clientId, clientMaps.clientSourceMap);
45
+ tosMap.set(clientId, clientMaps.clientTosMap);
46
+ break;
47
+ }
48
+ case 'unload-client': {
49
+ openChannels.delete(clientId);
50
+ this.disconnect();
51
+ break;
52
+ }
53
+ default:
54
+ break;
55
+ }
56
+ };
57
+ };
58
+ const createChannel = (clientId) => {
59
+ const listenerToSubscription = new Map();
60
+ const buffer = new ReplaySubject();
61
+ const sender = {
62
+ addEventListener(_, listener) {
63
+ listenerToSubscription.set(listener, buffer.subscribe((msg) => listener(msg)));
64
+ },
65
+ removeEventListener(_, listener) {
66
+ listenerToSubscription.get(listener)?.unsubscribe();
67
+ listenerToSubscription.delete(listener);
68
+ },
69
+ };
70
+ return {
71
+ buffer,
72
+ channel: new PostChannel(makeListener(clientId), sender, getReceiver(clientId)),
73
+ };
74
+ };
75
+ const getCachedOpenChannel = (clientId) => {
76
+ let ch = openChannels.get(clientId);
77
+ if (!ch) {
78
+ ch = createChannel(clientId);
79
+ openChannels.set(clientId, ch);
80
+ }
81
+ return ch;
82
+ };
83
+ self.addEventListener('install', () => {
84
+ // on service-worker.js update => immediate kill switch and update
85
+ // https://whatwebcando.today/articles/handling-service-worker-updates/
86
+ // https://stackoverflow.com/questions/33986976/how-can-i-remove-a-buggy-service-worker-or-implement-a-kill-switch/38980776#38980776
87
+ self.skipWaiting()
88
+ .catch((err) => console.error(`[SW] error while skipWaiting - ${String(err)}`));
89
+ });
90
+ self.addEventListener('activate', (event) => {
91
+ // all fetch events should be handled by the
92
+ // service worker as soon as active
93
+ event.waitUntil(self.clients.claim());
94
+ });
95
+ self.addEventListener('message', (message) => {
96
+ // messages allowed are `set-source-map` which replies with an
97
+ // acknowledgment `source-map-ack` that informs the client
98
+ // all is set to reverse proxy their fetch calls
99
+ const { source } = message;
100
+ if (!isWindowClient(source)) {
101
+ return;
102
+ }
103
+ const { id: clientId } = source;
104
+ getCachedOpenChannel(clientId).buffer.next(message);
105
+ });
106
+ self.addEventListener('fetch', (event) => {
107
+ const clientId = event.clientId !== '' ? event.clientId : event.resultingClientId;
108
+ const clientSourceMap = sourceMap.get(clientId);
109
+ if (!clientSourceMap) {
110
+ return event.respondWith(self.fetch(event.request));
111
+ }
112
+ // there must be a tosMap is clientSourceMap ain't undefined
113
+ const clientTosMap = tosMap.get(clientId);
114
+ let { request: { url } } = event;
115
+ const key = isAvailable(url, clientSourceMap);
116
+ const to = isAvailable(url, clientTosMap);
117
+ const headers = new Headers(event.request.headers);
118
+ let extraQuery = {};
119
+ if (key !== undefined) {
120
+ const value = clientSourceMap.get(key)?.to;
121
+ const extraHeaders = clientSourceMap.get(key)?.headers;
122
+ const rest = url.substring(key.length);
123
+ extraQuery = clientSourceMap.get(key)?.query;
124
+ url = `${value}${rest}`;
125
+ Object.entries(extraHeaders).forEach(([headerKey, headerValue]) => headers.set(headerKey, headerValue));
126
+ }
127
+ if (to !== undefined) {
128
+ const extraHeaders = clientTosMap.get(to);
129
+ Object.entries(extraHeaders).forEach(([headerKey, headerValue]) => headers.set(headerKey, headerValue));
130
+ }
131
+ let finalUrl;
132
+ try {
133
+ const urlInstance = new URL(url);
134
+ Object.entries(extraQuery).forEach(([qk, qv]) => urlInstance.searchParams.set(qk, qv));
135
+ finalUrl = urlInstance.href;
136
+ }
137
+ catch {
138
+ finalUrl = url;
139
+ }
140
+ console.log({ clientId, clientSourceMap, finalUrl });
141
+ event.respondWith(self.fetch(finalUrl, { ...event.request, headers })
142
+ .catch((error) => {
143
+ console.error(error);
144
+ return Promise.reject(error);
145
+ }));
146
+ });
@@ -0,0 +1,2 @@
1
+ export declare function parse(input: string, context: Record<string, unknown>, preserveUnknown?: boolean): string;
2
+ export declare const compileObject: <T extends Record<string, string>>(obj: T, context: Record<string, unknown>) => T;
@@ -0,0 +1,130 @@
1
+ var LexerState;
2
+ (function (LexerState) {
3
+ LexerState[LexerState["Literal"] = 0] = "Literal";
4
+ LexerState[LexerState["Normal"] = 1] = "Normal";
5
+ })(LexerState || (LexerState = {}));
6
+ class Lexer {
7
+ _input;
8
+ _length;
9
+ _idx = 0;
10
+ _mode = LexerState.Literal;
11
+ _literals = [];
12
+ _variables = [];
13
+ _braketCount = 0;
14
+ _done = false;
15
+ constructor(input) {
16
+ this._input = input;
17
+ this._length = input.length;
18
+ }
19
+ concatToLastLiteral(concat) {
20
+ // SAFETY: _literals here is always at least long 1
21
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
22
+ this._literals.push(this._literals.pop().concat(concat));
23
+ }
24
+ concatToLastVariable(concat) {
25
+ // SAFETY: _variables here is always at least long 1
26
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
27
+ this._variables.push(this._variables.pop().concat(concat));
28
+ }
29
+ get() {
30
+ const rawLiterals = [...this._literals];
31
+ const literals = Object.assign([], rawLiterals);
32
+ Object.defineProperty(literals, 'raw', { value: rawLiterals, writable: false });
33
+ return {
34
+ literals: literals,
35
+ variables: this._variables,
36
+ };
37
+ }
38
+ run() {
39
+ if (this._length === 0) {
40
+ this._literals.push('');
41
+ }
42
+ while (this._idx < this._length) {
43
+ const char = this._input.charAt(this._idx);
44
+ switch (this._mode) {
45
+ case LexerState.Literal: {
46
+ if (this._literals.length === 0) {
47
+ this._literals.push('');
48
+ }
49
+ if (char === '{'
50
+ && this._idx + 1 !== this._length
51
+ && this._input.charAt(this._idx + 1) === '{') {
52
+ this._literals.push('');
53
+ this._variables.push('');
54
+ this._mode = LexerState.Normal;
55
+ this._idx += 1;
56
+ }
57
+ else {
58
+ this.concatToLastLiteral(char);
59
+ }
60
+ break;
61
+ }
62
+ case LexerState.Normal:
63
+ if (char === '}' && this._input.charAt(this._idx + 1) === '}') {
64
+ this._mode = LexerState.Literal;
65
+ this._idx += 1;
66
+ }
67
+ else {
68
+ this.concatToLastVariable(char);
69
+ }
70
+ break;
71
+ default:
72
+ break;
73
+ }
74
+ this._idx += 1;
75
+ }
76
+ if (this._mode === LexerState.Normal) {
77
+ this._literals.pop();
78
+ // SAFETY: _variables here is always at least long 1
79
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
80
+ this.concatToLastLiteral(`{{${this._variables.pop()}`);
81
+ }
82
+ this._done = true;
83
+ }
84
+ }
85
+ const isSquareBrakets = (field) => {
86
+ const trimmed = field.trim();
87
+ if (!(trimmed.startsWith('[') && trimmed.endsWith(']'))) {
88
+ return false;
89
+ }
90
+ const inner = trimmed.slice(1).slice(0, -1).trim();
91
+ if (Number.parseInt(inner).toString(10) !== inner) {
92
+ return false;
93
+ }
94
+ return true;
95
+ };
96
+ const getNumber = (field) => {
97
+ return Number.parseInt(field.trim().slice(1).slice(0, -1)
98
+ .trim());
99
+ };
100
+ function interpolate(context, path, preserveUnknown) {
101
+ if (!path.trim()) {
102
+ return preserveUnknown ? `{{${path}}}` : '';
103
+ }
104
+ const result = path.trim().split('.').reduce((superctx, field) => {
105
+ if (Array.isArray(superctx) && isSquareBrakets(field)) {
106
+ return superctx[getNumber(field)];
107
+ }
108
+ if (typeof superctx === 'object' && superctx !== null && field in superctx) {
109
+ return superctx[field];
110
+ }
111
+ return undefined;
112
+ }, { ...context });
113
+ if (typeof result === 'string') {
114
+ return result;
115
+ }
116
+ return preserveUnknown ? `{{${path}}}` : '';
117
+ }
118
+ export function parse(input, context, preserveUnknown = false) {
119
+ const lexer = new Lexer(input);
120
+ lexer.run();
121
+ const template = lexer.get();
122
+ let [acc] = template.literals;
123
+ for (let i = 0; i < template.variables.length; i++) {
124
+ acc = acc
125
+ .concat(interpolate(context, template.variables[i], preserveUnknown))
126
+ .concat(template.literals[i + 1]);
127
+ }
128
+ return acc;
129
+ }
130
+ export const compileObject = (obj, context) => Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, parse(value, context)]));
@@ -0,0 +1,110 @@
1
+ import type { Manifest } from '@micro-lc/back-kit-engine/schemas';
2
+ import type { Component, PluginConfiguration } from '@micro-lc/interfaces/schemas/v2';
3
+ import type { SourceMapItems } from '../../service-worker';
4
+ interface TagInfo {
5
+ definitions?: Record<string, unknown>;
6
+ description?: string;
7
+ docLink?: string;
8
+ label?: string;
9
+ properties?: Manifest['properties'];
10
+ type?: Manifest['type'];
11
+ }
12
+ type OverlayMode = 0 | 'interact' | 'select';
13
+ interface InfoEntry {
14
+ info: TagInfo;
15
+ tag: string;
16
+ }
17
+ interface ElementContent {
18
+ ids: string[];
19
+ selectors: string[];
20
+ }
21
+ interface StyledElementContent extends ElementContent {
22
+ style: Partial<CSSStyleDeclaration>;
23
+ }
24
+ interface OptionMessage {
25
+ content: {
26
+ disableOverlay?: boolean;
27
+ redirectTo?: string;
28
+ run?: boolean;
29
+ timeout?: number;
30
+ };
31
+ type: 'options';
32
+ }
33
+ interface RequestResource {
34
+ content: Record<string, unknown>;
35
+ type: 'request-resource';
36
+ }
37
+ type RegisteredElementMessages = {
38
+ content: ElementContent | undefined;
39
+ type: 'click-element';
40
+ } | {
41
+ content: StyledElementContent | undefined;
42
+ type: 'focus-element';
43
+ };
44
+ interface NewConfiguration {
45
+ configuration: PluginConfiguration;
46
+ contexts: Map<string, Component[]>;
47
+ tags: string[];
48
+ }
49
+ interface NewConfigurationMessage {
50
+ content: NewConfiguration;
51
+ type: 'new-configuration';
52
+ }
53
+ interface UpdateConfiguration {
54
+ configuration: PluginConfiguration;
55
+ context: Component;
56
+ }
57
+ interface UpdateConfigurationMessage {
58
+ content: UpdateConfiguration;
59
+ type: 'update';
60
+ }
61
+ interface UpdatedMessage {
62
+ content: Record<string, never>;
63
+ type: 'updated';
64
+ }
65
+ type RegisteredConfigMessages = NewConfigurationMessage | UpdateConfigurationMessage;
66
+ type ReducedMouseEvent = Pick<MouseEvent, 'bubbles' | 'cancelable' | 'clientX' | 'clientY'>;
67
+ interface SourceMapMessage {
68
+ content: SourceMapItems;
69
+ type: 'set-source-map';
70
+ }
71
+ type RegisteredMessages = {
72
+ content: ReducedMouseEvent;
73
+ type: 'mousedown' | 'mousemove';
74
+ } | {
75
+ content: NotifyProps;
76
+ type: 'notification';
77
+ } | {
78
+ content: {
79
+ mode: OverlayMode;
80
+ };
81
+ type: 'ctrl-space';
82
+ } | {
83
+ content: InfoEntry[];
84
+ type: 'tag-info';
85
+ } | RegisteredConfigMessages | UpdatedMessage | RegisteredElementMessages | OptionMessage | RequestResource | SourceMapMessage;
86
+ interface NotifyProps extends Record<string, unknown> {
87
+ data?: Record<string, string>;
88
+ description: string;
89
+ message: string;
90
+ status: 'info' | 'error' | 'default' | 'success' | 'processing' | 'warning' | undefined;
91
+ }
92
+ interface Reset {
93
+ configuration: PluginConfiguration;
94
+ contexts: Map<string, Component[]>;
95
+ tags: string[];
96
+ type: 'reset';
97
+ }
98
+ interface SingleUpdate {
99
+ configuration: PluginConfiguration;
100
+ context: Component;
101
+ type: 'update';
102
+ }
103
+ type Update = Reset | SingleUpdate;
104
+ declare const MIA_PREVIEW_ID = "__mia_preview_id";
105
+ declare const OVERLAY_Z_INDEX = 1000000;
106
+ declare const DEFAULT_MODE = "select";
107
+ declare function isRegisteredMessage(input: unknown): input is RegisteredMessages;
108
+ export type { NewConfiguration, UpdateConfiguration, OverlayMode, TagInfo, InfoEntry, ElementContent, StyledElementContent, NewConfigurationMessage, UpdateConfigurationMessage, RegisteredConfigMessages, RegisteredMessages, OptionMessage, NotifyProps, Reset, Update, RequestResource, SourceMapItems, };
109
+ export { MIA_PREVIEW_ID, OVERLAY_Z_INDEX, DEFAULT_MODE, isRegisteredMessage, };
110
+ export * from './handlebars';