# LIFF plugin
# What is LIFF plugin
LIFF plugin is a feature to extend the LIFF SDK. Using a LIFF plugin, you can add your own APIs to the LIFF SDK or change the behavior of LIFF APIs.
A LIFF plugin is an object or a class with specific properties and a specific method.
# Operating environment of LIFF Plugin
LIFF plugin is available in LIFF v2.19.0 or later.
# Using a LIFF plugin
Use the liff.use()
method to activate a LIFF plugin. Passing a LIFF plugin to the liff.use()
method activates the LIFF plugin. When the LIFF plugin is activated, the liff
object will be extended and the API of the LIFF plugin will be available.
The following is an example of activating a LIFF plugin called GreetPlugin
and executing the liff.$greet.hello()
method.
# If the LIFF plugin is a class
If the LIFF plugin is a class, you need to pass the instance to the liff.use()
method.
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return {
hello: this.hello,
};
}
hello() {
console.log("Hello, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet.hello(); // Hello, World!
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
# If the LIFF plugin is an object
const hello = () => {
console.log("Hello, World!");
};
const greetPlugin = {
name: "greet",
install() {
return {
hello,
};
},
};
liff.use(greetPlugin);
liff.$greet.hello(); // Hello, World!
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
As you can see above, when a LIFF plugin is activated, a property is added to the liff
object with a $
prefix to the value of the name
property. This allows you to use the API of a LIFF plugin in liff.${value of the name property of the LIFF plugin}.{property name}
and liff.${value of the name property of the LIFF plugin}.{method name}()
formats.
# Creating a LIFF plugin
You can create a LIFF plugin as an object or a class that has the name
property and the install()
method.
The following is an example of a LIFF plugin called GreetPlugin
which offers the hello
method and the goodbye()
method as APIs.
# If the LIFF plugin is a class
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return {
hello: this.hello,
goodbye: this.goodbye,
};
}
hello() {
console.log("Hello, World!");
}
goodbye() {
console.log("Goodbye, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet.hello(); // Hello, World!
liff.$greet.goodbye(); // Goodbye, World!
# If the LIFF plugin is an object
const hello = () => {
console.log("Hello, World!");
};
const goodbye = () => {
console.log("Goodbye, World!");
};
const greetPlugin = {
name: "greet",
install() {
return {
hello,
goodbye,
};
},
};
liff.use(greetPlugin);
liff.$greet.hello(); // Hello, World!
liff.$greet.goodbye(); // Goodbye, World!
# name propery
The value of the name
property is the name of a LIFF plugin. Specify the name
property a string.
The specified value will be the property name of the liff
object, as in liff.${value of the name property of the LIFF plugin}
.
# install() method
The install()
method is a function that does the following:
# Describing the initialization process of the LIFF plugin
The install()
method will be executed by the liff.use()
method when the LIFF plugin is activated. Therefore, you can describe the initialization process of the LIFF plugin within the install()
method.
# Defining the API of the LIFF plugin
The API of the LIFF plugin is defined as the return value of the install()
method. You can define multiple APIs by returning an object.
If the LIFF plugin has only one API, it's possible to use that API as the return value. The following is an example of the install()
method that returns a function instead of an object.
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return this.hello;
}
hello() {
console.log("Hello, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet(); // Hello, World!
# Arguments of the install()
method
The install()
method takes a context
object as the first argument and an option
as the second argument.
class GreetPlugin {
constructor() {
this.name = "greet";
}
install(context, option) {}
}
# context
object
The first argument of the install()
method. The context
object has the following two properties:
Property | Value |
---|---|
liff | liff object |
hooks | Object that provides methods for registering a callback on a hook |
# option
The second argument of the install()
method. The value specified in the second argument of the liff.use()
method is passed. If the second argument of the liff.use()
method is unspecified, the value of option
will be undefined
.
You can use option
to customize the behavior of a LIFF plugin by passing an argument to the liff.use()
method.
# About hook
Hook is a mechanism in LIFF plugin that allows pre-registered callbacks to be executed at a specific time during the processing of a LIFF API. You can think of hook in the same way as event processing in JavaScript. If a callback is registered with a hook, the callback will be executed at the timing when the hook is fired.
In addition to using hooks provided by the LIFF API, LIFF plugins can provide their own hooks.
# Hooks for LIFF API
At this time, the LIFF API provides hooks only for the liff.init()
method.
LIFF API | Hook | Hook type | When the hook fires |
---|---|---|---|
liff.init() method | before hook | async hook | Immediately after calling liff.init() (before the initialization of a LIFF app) |
after hook | async hook | Immediately before calling successCallback (after the initialization of a LIFF app) |
# Hook types
There are two types of hooks: sync hook and async hook.
# Sync hook
Sync hook processes registered callbacks synchronously. Registered callbacks are processed in the order in which they are registered. The return value of registered callbacks is ignored.
# Async hook
Async hook processes registered callbacks asynchronously. Registered callbacks are processed in parallel using the Promise.all()
method. The return value of registered callbacks must be a Promise
object.
# Registering a callback on a hook
To register a callback on a hook, use the context.hooks
property of the install()
method.
The following is an example of registering callbacks on the before
hook and the after
hook of the liff.init()
method. When the liff.init()
method is executed, the before
hook and the after
hook will fire, and the registered callbacks will be executed.
Note that the before
hook and the after
hook are async hooks, so the registered callbacks must return a Promise
object.
class GreetPlugin {
constructor() {
this.name = "greet";
}
install(context) {
context.hooks.init.before(this.initBefore);
context.hooks.init.after(this.initAfter);
return {
hello: this.hello,
goodbye: this.goodbye,
};
}
hello() {
console.log("Hello, World!");
}
goodbye() {
console.log("Goodbye, World!");
}
initBefore() {
console.log("before hook is called");
return Promise.resolve();
}
initAfter() {
console.log("after hook is called");
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
# Creating a hook
You can create a hook as an instance of the SyncHook
class or the AsyncHook
class.
Hook type | Class |
---|---|
sync hook | SyncHook |
async hook | AsyncHook |
The following is an example of creating hooks called helloBefore
and helloAfter
. Note that you need to import the SyncHook
class and the AsyncHook
class from the @liff/hooks
package.
To fire the created hooks, execute the call()
method of the instances of the SyncHook
class and the AsyncHook
class.
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call();
console.log("Hello, World!");
this.hooks.helloAfter.call();
}
goodbye() {
console.log("Goodbye, World!");
}
}
The hooks created can be used by other LIFF plugins to register callbacks. The following is an example of registering callbacks on the helloBefore
hook and the helloAfter
hook of a LIFF plugin called GreetPlugin
.
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call();
console.log("Hello, World!");
this.hooks.helloAfter.call();
}
goodbye() {
console.log("Goodbye, World!");
}
}
class OtherPlugin {
constructor() {
this.name = "other";
}
install(context) {
context.hooks.$greet.helloBefore(this.greetBefore);
context.hooks.$greet.helloAfter(this.greetAfter);
}
greetBefore() {
console.log("helloBefore hook is called");
}
greetAfter() {
console.log("helloAfter hook is called");
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff.use(new OtherPlugin());
liff.$greet.hello();
// helloBefore hook is called
// Hello, World!
// helloAfter hook is called
# call()
method
The call()
method is a function to fire a hook. You can pass any number of arguments to the call()
method. The arguments passed to the call()
method can be received as arguments by callbacks registered with the hook.
The following is an example of passing arguments to the call()
method of hooks and having callbacks receive them.
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call("foo");
console.log("Hello, World!");
this.hooks.helloAfter.call("foo", 0);
}
goodbye() {
console.log("Goodbye, World!");
}
}
class OtherPlugin {
constructor() {
this.name = "other";
}
install(context) {
context.hooks.$greet.helloBefore(this.greetBefore);
context.hooks.$greet.helloAfter(this.greetAfter);
}
greetBefore(foo) {
console.log(foo); // foo
}
greetAfter(foo, bar) {
console.log(foo, bar); // foo 0
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff.use(new OtherPlugin());
liff.$greet.hello(); // Hello, World!
# Official LIFF plugins
We provide the following official LIFF plugins:
# LIFF Inspector
LIFF Inspector is a LIFF plugin to debug your LIFF app. Using LIFF Inspector, you can debug your LIFF app with Chrome DevTools (opens new window) on a different PC than the device on which you are running the LIFF app.
Fore more information on LIFF Inspector, see the README (opens new window) on GitHub or the Readme tab on npm (opens new window).
# LIFF Mock
LIFF Mock is a LIFF plugin to make testing your LIFF app easy. Using LIFF Mock, you can add the mock mode to the LIFF SDK. In the mock mode, your LIFF app is independent of the LIFF server and the LIFF API returns mock data. Therefore, you can perform unit testing or load testing more easily.
Fore more information on LIFF Mock, see the README (opens new window) on GitHub or the Readme tab on npm (opens new window).