Awesome
:warning: Please check chromite
and jstorm
:warning:
This project is splitted and transfered to following projects:
chomex
Chrome Extension Messaging Routing Kit.
- Router to handle
onMessage
with routes expression - Client to Promisify
sendMessage
- Model to access to
localStorage
likeActiveRecord
- Types to define data schema of
Model
Installation
npm install chomex
Why?
.onMessage
like a server routing
:-1: Dispatching message inside addListener
function makes my code messy and unreeadable.
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch(message.action) {
case "/users/get":
GetUser.apply(sender, [message, sendResponse]);
break;
default:
NotFound.apply(sender, [message, sendResponse]);
}
return true;
});
:+1: chomex.Router
makes it more claen and readable.
const router = new chomex.Router();
router.on("/users/get", GetUser);
chrome.runtime.onMessage.addListener(router.listener());
Happy :hugs:
.sendMessage
like a fetch client
:-1: Handling the response of sendMessage
by callback makes my code messy and unreadable.
chrome.runtime.sendMessage({action:"/users/get",id:123}, (response) => {
if (response.status == 200) {
alert("User: " + response.user.name);
} else {
console.log("Error:", response);
}
});
:+1: chomex.Client
makes it clean and readable by handling response with Promise
.
const client = new chomex.Client(chrome.runtime);
const response = await client.message("/users/get", {id:123});
alert("User: " + response.data.user.name);
Happy :hugs:
Examples
NOTE: These examples are using async/await on top-level. I believe you are familiar with asyc/await.
background.js
as a server
import {Router, Model, Types} from 'chomex';
// Define your model
class User extends Model {
static schema = {
name: Types.string.isRequired,
age: Types.number,
}
}
const router = new Router();
// Define your routes
router.on("/users/create", message => {
const obj = message.user;
const user = User.new(obj).save();
return user;
});
router.on("/users/get", message => {
const userId = message.id;
const user = User.find(userId);
if (!user) {
return {status:404,error:"not found"};
}
// You can also return async Promise
return Promise.resolve(user);
});
// Of course, you can separate files
// in which controller functions are defined.
import {UserDelete} from "./Controllers/Users";
router.on("/users/delete", UserDelete);
// Don't forget to add listener to chrome modules.
chrome.runtime.onMessage.addListener(router.listener());
content_script.js
as a client
import {Client} from 'chomex';
const client = new Client(chrome.runtime);
// it sends message to "/users/get" route.
const user = {name: 'otiai10', age: 30};
const response = await client.message('/users/create', {user});
console.log("Created!", response.data);
const {data: user} = await client.message('/users/get', {id: 12345});
console.log("Found:", res.data);
Customize Router
for other listeners
You can also customize resolver for routing.
It's helpful when you want to make routings for EventListener modules on chrome
, such as chrome.notifications.onClicked
, chrome.webRequest.onBeforeRequest
or so.
// Resolver rule, which resolve given "id" to routing name.
const resolve = (id) => {
const prefix = id.split(".")[0];
return {name: prefix};
};
const router = new Router(resolve);
// You see, this controller is invoked when
// a notification with ID "quest.xxxx" is clicked.
router.on('quest', NotificaionOnClickController.Quest);
chrome.notifications.onClicked.addListener(router.listener());
For more information
Reference Projects
Projects using chomex