webext-messenger 0.22.0-4 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  import { __getTabData } from "./thisTarget.js";
2
- import { Method } from "./types.js";
2
+ import { type Method } from "./types.js";
3
3
  declare global {
4
4
  interface MessengerMethods {
5
5
  __getTabData: typeof __getTabData;
@@ -1,4 +1,4 @@
1
1
  export * from "./receiver.js";
2
2
  export * from "./sender.js";
3
3
  export * from "./types.js";
4
- export { getThisTarget } from "./thisTarget.js";
4
+ export { getThisFrame, getTopLevelFrame } from "./thisTarget.js";
@@ -2,6 +2,6 @@
2
2
  export * from "./receiver.js";
3
3
  export * from "./sender.js";
4
4
  export * from "./types.js";
5
- export { getThisTarget } from "./thisTarget.js";
5
+ export { getThisFrame, getTopLevelFrame } from "./thisTarget.js";
6
6
  import { initPrivateApi } from "./thisTarget.js";
7
7
  initPrivateApi();
@@ -1,3 +1,3 @@
1
- import { Message } from "./types.js";
1
+ import { type Message } from "./types.js";
2
2
  export declare function isMessengerMessage(message: unknown): message is Message;
3
3
  export declare function registerMethods(methods: Partial<MessengerMethods>): void;
@@ -1,5 +1,5 @@
1
- import { PublicMethod, PublicMethodWithTarget, Options, Target, PageTarget } from "./types.js";
2
- import { SetReturnType } from "type-fest";
1
+ import { type PublicMethod, type PublicMethodWithTarget, type Options, type Target, type PageTarget } from "./types.js";
2
+ import { type SetReturnType } from "type-fest";
3
3
  export declare const errorTargetClosedEarly = "The target was closed before receiving a response";
4
4
  export declare const errorTabDoesntExist = "The tab doesn't exist";
5
5
  declare function messenger<Type extends keyof MessengerMethods, Method extends MessengerMethods[Type]>(type: Type, options: {
@@ -1,5 +1,5 @@
1
- import { JsonObject } from "type-fest";
2
- declare type ErrorObject = {
1
+ import { type JsonObject } from "type-fest";
2
+ type ErrorObject = {
3
3
  name?: string;
4
4
  stack?: string;
5
5
  message?: string;
@@ -1,5 +1,6 @@
1
- import { AnyTarget, KnownTarget, Message, MessengerMeta, Sender } from "./types.js";
1
+ import { type AnyTarget, type TopLevelFrame, type Message, type MessengerMeta, type Sender, type FrameTarget } from "./types.js";
2
2
  export declare function getActionForMessage(from: Sender, message: Message): "respond" | "forward" | "ignore";
3
3
  export declare function __getTabData(this: MessengerMeta): AnyTarget;
4
- export declare function getThisTarget(): Promise<KnownTarget>;
4
+ export declare function getThisFrame(): Promise<FrameTarget>;
5
+ export declare function getTopLevelFrame(): Promise<TopLevelFrame>;
5
6
  export declare function initPrivateApi(): void;
@@ -29,16 +29,17 @@ const thisTarget = isBackground()
29
29
  ? { page: "background" }
30
30
  : {
31
31
  get page() {
32
- return location.pathname + location.search;
32
+ // Extension pages have relative URLs to simplify comparison
33
+ const origin = location.protocol.startsWith("http")
34
+ ? location.origin
35
+ : "";
36
+ // Don't use the hash
37
+ return origin + location.pathname + location.search;
33
38
  },
34
39
  };
35
40
  let tabDataStatus =
36
41
  // The background page doesn't have a tab
37
- isBackground() ||
38
- // Content scripts don't use named targets yet
39
- isContentScript()
40
- ? "not-needed"
41
- : "needed";
42
+ isBackground() ? "not-needed" : "needed";
42
43
  function compareTargets(to, thisTarget) {
43
44
  for (const [key, value] of Object.entries(to)) {
44
45
  if (thisTarget[key] === value) {
@@ -112,9 +113,21 @@ const storeTabData = once(async () => {
112
113
  export function __getTabData() {
113
114
  return { tabId: this.trace[0]?.tab?.id, frameId: this.trace[0]?.frameId };
114
115
  }
115
- export async function getThisTarget() {
116
+ export async function getThisFrame() {
116
117
  await storeTabData(); // It should already have been called by we still need to await it
117
- return thisTarget;
118
+ const { tabId, frameId } = thisTarget;
119
+ if (typeof tabId !== "number" || typeof frameId !== "number") {
120
+ throw new TypeError("This target is not in a frame");
121
+ }
122
+ // Rebuild object to return exactly these two properties and nothing more
123
+ return { tabId, frameId };
124
+ }
125
+ export async function getTopLevelFrame() {
126
+ const { tabId } = await getThisFrame();
127
+ return {
128
+ tabId,
129
+ frameId: 0,
130
+ };
118
131
  }
119
132
  export function initPrivateApi() {
120
133
  if (isExtensionContext()) {
@@ -1,30 +1,35 @@
1
- import { Runtime } from "webextension-polyfill";
2
- import { Asyncify, ValueOf } from "type-fest";
3
- import { ErrorObject } from "serialize-error";
1
+ import { type Runtime } from "webextension-polyfill";
2
+ import { type Asyncify, type ValueOf } from "type-fest";
3
+ import { type ErrorObject } from "serialize-error";
4
+ /**
5
+ * @file Target types are a bit overlapping. That's because some are "request" targets
6
+ * and some are "known" targets. The difference is that you could "request" `{tabId: 1}`, but you "know" that a specific target is exactly `{tabId: 1, frameId: 5}`
7
+ * TODO: Cleanup, clarify, deduplicate Target types
8
+ */
4
9
  declare global {
5
10
  interface MessengerMethods {
6
11
  _: Method;
7
12
  }
8
13
  }
9
- declare type WithTarget<Method> = Method extends (...args: infer PreviousArguments) => infer TReturnValue ? (target: Target | PageTarget, ...args: PreviousArguments) => TReturnValue : never;
10
- declare type ActuallyOmitThisParameter<T> = T extends (...args: infer A) => infer R ? (...args: A) => R : T;
14
+ type WithTarget<Method> = Method extends (...args: infer PreviousArguments) => infer TReturnValue ? (target: Target | PageTarget, ...args: PreviousArguments) => TReturnValue : never;
15
+ type ActuallyOmitThisParameter<T> = T extends (...args: infer A) => infer R ? (...args: A) => R : T;
11
16
  /** Removes the `this` type and ensure it's always Promised */
12
- export declare type PublicMethod<Method extends ValueOf<MessengerMethods>> = Asyncify<ActuallyOmitThisParameter<Method>>;
13
- export declare type PublicMethodWithTarget<Method extends ValueOf<MessengerMethods>> = WithTarget<PublicMethod<Method>>;
17
+ export type PublicMethod<Method extends ValueOf<MessengerMethods>> = Asyncify<ActuallyOmitThisParameter<Method>>;
18
+ export type PublicMethodWithTarget<Method extends ValueOf<MessengerMethods>> = WithTarget<PublicMethod<Method>>;
14
19
  export interface MessengerMeta {
15
20
  trace: Sender[];
16
21
  }
17
- declare type RawMessengerResponse = {
22
+ type RawMessengerResponse = {
18
23
  value: unknown;
19
24
  } | {
20
25
  error: ErrorObject;
21
26
  };
22
- export declare type MessengerResponse = RawMessengerResponse & {
27
+ export type MessengerResponse = RawMessengerResponse & {
23
28
  /** Guarantees that the message was handled by this library */
24
29
  __webextMessenger: true;
25
30
  };
26
- declare type Arguments = any[];
27
- export declare type Method = (this: MessengerMeta, ...args: Arguments) => Promise<unknown>;
31
+ type Arguments = any[];
32
+ export type Method = (this: MessengerMeta, ...args: Arguments) => Promise<unknown>;
28
33
  export interface Options {
29
34
  /**
30
35
  * "Notifications" won't await the response, return values, attempt retries, nor throw errors
@@ -33,17 +38,17 @@ export interface Options {
33
38
  isNotification?: boolean;
34
39
  trace?: Sender[];
35
40
  }
36
- export declare type Message<LocalArguments extends Arguments = Arguments> = {
41
+ export type Message<LocalArguments extends Arguments = Arguments> = {
37
42
  type: keyof MessengerMethods;
38
43
  args: LocalArguments;
39
44
  target: Target | PageTarget;
40
45
  /** If the message is being sent to an intermediary receiver, also set the options */
41
46
  options?: Options;
42
47
  };
43
- export declare type Sender = Runtime.MessageSender & {
48
+ export type Sender = Runtime.MessageSender & {
44
49
  origin?: string;
45
50
  };
46
- export declare type MessengerMessage = Message & {
51
+ export type MessengerMessage = Message & {
47
52
  /** Guarantees that a message is meant to be handled by this library */
48
53
  __webextMessenger: true;
49
54
  };
@@ -52,6 +57,14 @@ export interface AnyTarget {
52
57
  frameId?: number;
53
58
  page?: string;
54
59
  }
60
+ export interface TopLevelFrame {
61
+ tabId: number;
62
+ frameId: 0;
63
+ }
64
+ export interface FrameTarget {
65
+ tabId: number;
66
+ frameId: number;
67
+ }
55
68
  export interface KnownTarget {
56
69
  tabId?: number;
57
70
  frameId?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webext-messenger",
3
- "version": "0.22.0-4",
3
+ "version": "0.22.0",
4
4
  "description": "Browser Extension component messaging framework",
5
5
  "keywords": [],
6
6
  "repository": "pixiebrix/webext-messenger",
@@ -21,25 +21,19 @@
21
21
  "dependencies": {
22
22
  "p-retry": "^5.1.1",
23
23
  "serialize-error": "^11.0.0",
24
- "type-fest": "^2.13.0",
24
+ "type-fest": "^3.2.0",
25
25
  "webext-detect-page": "^4.0.1",
26
26
  "webext-tools": "^1.1.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@parcel/config-webextension": "^2.6.0",
29
+ "@parcel/config-webextension": "^2.8.0",
30
30
  "@sindresorhus/tsconfig": "^3.0.1",
31
- "@types/chrome": "^0.0.188",
31
+ "@types/chrome": "^0.0.203",
32
32
  "@types/tape": "^4.13.2",
33
33
  "@types/webextension-polyfill": "^0.9.0",
34
- "@typescript-eslint/eslint-plugin": "^5.27.0",
35
- "@typescript-eslint/parser": "^5.27.0",
36
34
  "buffer": "^6.0.3",
37
- "eslint": "^8.17.0",
38
- "eslint-config-prettier": "^8.5.0",
39
- "eslint-config-xo": "^0.41.0",
40
- "eslint-config-xo-typescript": "^0.51.1",
41
- "eslint-plugin-import": "^2.26.0",
42
- "eslint-plugin-unicorn": "^42.0.0",
35
+ "eslint": "^8.28.0",
36
+ "eslint-config-pixiebrix": "^0.20.0",
43
37
  "events": "^3.3.0",
44
38
  "npm-run-all": "^4.1.5",
45
39
  "parcel": "^2.6.0",
@@ -47,9 +41,9 @@
47
41
  "process": "^0.11.10",
48
42
  "stream-browserify": "^3.0.0",
49
43
  "tape": "^5.5.3",
50
- "typescript": "^4.7.3",
44
+ "typescript": "^4.9.3",
51
45
  "webext-content-scripts": "^1.0.2",
52
- "webextension-polyfill": "^0.9.0"
46
+ "webextension-polyfill": "^0.10.0"
53
47
  },
54
48
  "alias": {
55
49
  "./this-stuff-is-just-for-local-parcel-tests": "https://github.com/parcel-bundler/parcel/issues/4936",