@Pallas how can I calculate dynamically matches url property on config base on storage?
@Pallas how can I calculate dynamically matches url property on config base on storage?
chrome.storage API to store and retrieve data. To dynamically match a URL property based on storage configuration, you can first retrieve the configuration data from storage using chrome.storage.sync.get(). Once you have the configuration data, you can use it to construct a regular expression that matches the desired URLs. http:// or https:// and contains one of the domains specified in the configuration data.calculateMatches function on the PlasmoCSConfig object.calculateMatches function:PlasmoCSConfig, and then passing in an input string to the calculateMatches function. The function will return an array of matches that were found in the input string.getRandomValues function is not available in the crypto object. This function is used to generate cryptographically secure random numbers, and is required for the randomBytes function to work properly.crypto object is imported from the crypto_1 module. This module is not a standard part of the browser environment, and is typically used in Node.js environments. window.crypto object instead of crypto_1.crypto. This object is available in modern browsers and provides the same functionality as the crypto module in Node.js.randomBytes function that uses window.crypto:randomBytes function to generate secure random numbers in your browser extension.PlasmoCSConfig class, but it's not working because PlasmoCSConfig is a type, not a constructor. To create a new instance of the PlasmoCSConfig class, you'll need to use the new keyword with the constructor function.PlasmoCSConfig object and calculate the matches property when the tsx file is loaded:PlasmoCSConfig class from the plasmo package and create a new instance of it with our custom properties. We then add an event listener to the DOMContentLoaded event, which fires when the tsx file is loaded. In the event listener, we call a function to calculate the matches property and set it on our custom config object.export keyword within the promise's callback function. Here's an example:myConfig object within the promise's callback function. We then use the export keyword to export the myConfig object. Finally, we resolve the promise and log a message to the console to confirm that the object was exported.chrome.contentScripts.register API. Here's an example:https://www.example.com/*. The js and css properties specify the files that should be injected into the page. The runAt property specifies when the script should be injected (in this case, at the end of the document). The allFrames property specifies whether the script should run in all frames of the page. Finally, the excludeGlobs property specifies any URL patterns that should be excluded from the content script.chrome.scripting.getRegisteredContentScripts function to retrieve information about the content scripts that have been registered for a particular extension. This can be useful if you need to dynamically modify or remove content scripts based on user preferences or other factors.chrome.scripting.getRegisteredContentScripts function to retrieve information about all the content scripts that have been registered for our extension. We're passing in an options object that specifies the extension ID (which we can get from chrome.runtime.id) and a callback function that will be called with an array of content script objects.js array), as well as the list of URL patterns that the script matches (which is stored in the matches array).chrome.storage.sync, you would use chrome.storage.local. chrome.runtime.onMessage event to listen for messages sent between the two scripts. When a message is received, you can then update the local storage accordingly. redux-persist to persist your Redux state, but you are encountering an error that says TypeError: Cannot read properties of undefined (reading 'local'). This error is usually caused by a misconfiguration of the storage option in your persistConfig.storage option is undefined, which means that redux-persist is trying to read the local property of an undefined object. This could happen if you forgot to import the storage library that you are using, or if you misspelled the name of the storage library.redux-persist-webextension-storage to persist your Redux state in a browser extension, make sure that you have installed the library and imported it correctly in your code. Here's an example of how you can configure redux-persist to use redux-persist-webextension-storage:storage from redux-persist-webextension-storage and use it as the storage option in our persistConfig. This should allow redux-persist to correctly store and retrieve your Redux state in the browser's storage.import statement, and will instead use the native ES module system of Chrome 91.import statement to a format that is compatible with Internet Explorer 11.Storage interface provided by @plasmohq/storage. Specifically, it is saying that the getAllKeys property is missing from the StorageInterface type, which is required by the Storage type.@plasmohq/storage to include the StorageInterface type explicitly. Here's an example:persistConfig object to use the StorageInterface type instead of the Storage type:localStorage as StorageInterface, you are telling TypeScript to treat it as if it has the getAllKeys property, even though it is not explicitly defined in the Storage type.chrome.storage as undefined, it means that you have not requested the storage permission in your extension's manifest file. To enable it, you need to add the following line to your manifest.json file:"permissions" field is an array of strings that lists all the permissions that your extension requires. In this case, we are requesting the storage permission.chrome.storage API in your extension without any issues.storage permission explicitly. Plasmo's Storage class abstracts the chrome.storage API and falls back to localStorage when the extension storage API is unavailable. This allows for state sync between extension pages, content scripts, background service workers, and web pages.package.json file. "storage" permission to the "permissions" array in your package.json file. Here's an example:"storage" permission to the "permissions" array. This will allow your extension to use the storage API provided by Plasmo."storage" permission to your package.json file, you can use the @plasmohq/storage library to interact with the storage API. This library abstracts the persistent storage API available to browser extensions and falls back to localStorage when the extension storage API is unavailable.@plasmohq/storage library to store and retrieve data:useStorage hook from the @plasmohq/storage library to store and retrieve data. The useStorage hook takes two arguments: the key to use for storing the data, and the default value to use if there is no existing value for the key.@plasmohq/storage library and adding the "storage" permission to your package.json file, you can easily store and retrieve data in your Plasmo-based browser extension.pnpm create plasmo?/Users/brendanbuono/src/plasmo/cli/create-plasmoconst config = await new Promise(resolve => {
chrome.storage.sync.get('config', resolve);
});
const domains = config.domains.join('|');
const regex = new RegExp(`^https?://(${domains})/`);import { PlasmoCSConfig } from 'plasmo';
const config = new PlasmoCSConfig();
const input = 'example input';
const matches = config.calculateMatches(input);
console.log(matches);exports.wrapConstructorWithOpts = wrapConstructorWithOpts;
/**
* Secure PRNG. Uses `globalThis.crypto` or node.js crypto module.
*/ function randomBytes(bytesLength = 32) {
if (crypto_1.crypto && typeof crypto_1.crypto.getRandomValues === "function") return crypto_1.crypto.getRandomValues(new Uint8Array(bytesLength));
throw new Error("crypto.getRandomValues must be defined");
}function randomBytes(bytesLength = 32) {
if (window.crypto && typeof window.crypto.getRandomValues === "function") {
return window.crypto.getRandomValues(new Uint8Array(bytesLength));
}
throw new Error("crypto.getRandomValues must be defined");
}import { PlasmoCSConfig } from 'plasmo';
// Define your custom config object
const myConfig = new PlasmoCSConfig({
// Set your custom properties here
// ...
});
// Calculate the matches property when the tsx file is loaded
document.addEventListener('DOMContentLoaded', () => {
const matches = calculateMatches();
myConfig.matches = matches;
});
// Function to calculate the matches property
function calculateMatches() {
// ...
}const myPromise = new Promise((resolve, reject) => {
const myConfig = {
option1: true,
option2: false
};
export { myConfig };
resolve();
});
myPromise.then(() => {
console.log('Exported myConfig object!');
});chrome.contentScripts.register({
matches: ['https://www.example.com/*'],
js: [{file: 'content.js'}],
css: [{file: 'content.css'}],
runAt: 'document_end',
allFrames: true,
excludeGlobs: ['**/exclude/**']
});chrome.scripting.getRegisteredContentScripts({ extensionId: chrome.runtime.id }, (scripts) => {
console.log(`Found ${scripts.length} registered content scripts:`);
scripts.forEach((script) => {
console.log(`- ${script.js[0]} (${script.matches.join(', ')})`);
});
});chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'update') {
chrome.storage.local.set({ data: message.data });
}
});chrome.storage.local.get('data', (result) => {
// Do something with the data
});
// Send a message to the background script to update the data
chrome.runtime.sendMessage({ type: 'update', data: newData });import { persistReducer } from 'redux-persist';
import storage from 'redux-persist-webextension-storage';
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);import { someFunction } from './myModule.js';
chrome.runtime.onMessage.addListener((message) => {
someFunction(message);
});import { someFunction } from './myModule.js';
chrome.runtime.onMessage.addListener((message) => {
someFunction(message);
});import { combineReducers, configureStore } from "@reduxjs/toolkit"
import {
type TypedUseSelectorHook,
useDispatch,
useSelector
} from "react-redux"
import { syncStorage,localStorage } from "redux-persist-webextension-storage"
import {
FLUSH,
PAUSE,
PERSIST,
PURGE,
REGISTER,
REHYDRATE,
RESYNC,
persistReducer,
persistStore
} from "@plasmohq/redux-persist"
import { Storage } from "@plasmohq/storage"
import appReducer from "./app/appReducer"
const rootReducer = combineReducers({
app: appReducer
})
const persistConfig = {
key: "root",
version: 1,
storage: localStorage
}
const persistedReducer = persistReducer(persistConfig, rootReducer)const persistConfig = {
key: "root",
version: 1,
storage: localStorage as StorageInterface
}{
"name": "My Extension",
"version": "1.0",
"manifest_version": 2,
"permissions": [
"storage"
],
"background": {
"scripts": ["background.js"],
"persistent": false
}
}{
"name": "my-extension",
"version": "1.0.0",
"description": "My awesome extension",
"permissions": [
"storage"
],
"devDependencies": {
"@plasmohq/plasmo": "^1.0.0"
}
}import { useStorage } from '@plasmohq/storage';
const MyComponent = () => {
const [value, setValue] = useStorage('my-key', 'default-value');
const handleClick = () => {
setValue('new-value');
};
return (
<div>
<p>Current value: {value}</p>
<button onClick={handleClick}>Update value</button>
</div>
);
};/Users/brendanbuono/src/plasmo/cli/create-plasmo