wxt 0.12.5 → 0.13.1-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JK5CNMJT.js → chunk-UMDTDPYN.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/storage.cjs +312 -83
- package/dist/storage.d.cts +185 -12
- package/dist/storage.d.ts +185 -12
- package/dist/storage.js +311 -84
- package/dist/testing.js +1 -1
- package/dist/vite-builder-env.d.ts +1 -0
- package/package.json +5 -2
package/dist/storage.js
CHANGED
|
@@ -1,108 +1,335 @@
|
|
|
1
1
|
import "./chunk-VBXJIVYU.js";
|
|
2
2
|
|
|
3
|
-
// src/storage.ts
|
|
4
|
-
import {
|
|
5
|
-
createStorage,
|
|
6
|
-
defineDriver
|
|
7
|
-
} from "unstorage";
|
|
8
|
-
|
|
9
3
|
// src/browser.ts
|
|
10
4
|
import originalBrowser from "webextension-polyfill";
|
|
11
5
|
var browser = originalBrowser;
|
|
12
6
|
|
|
13
7
|
// src/storage.ts
|
|
14
|
-
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
import { dequal } from "dequal/lite";
|
|
9
|
+
var storage = createStorage();
|
|
10
|
+
function createStorage() {
|
|
11
|
+
const drivers = {
|
|
12
|
+
local: createDriver("local"),
|
|
13
|
+
session: createDriver("session"),
|
|
14
|
+
sync: createDriver("sync"),
|
|
15
|
+
managed: createDriver("managed")
|
|
16
|
+
};
|
|
17
|
+
const getDriver = (area) => {
|
|
18
|
+
const driver = drivers[area];
|
|
19
|
+
if (driver == null) {
|
|
20
|
+
const areaNames = Object.keys(drivers).join(", ");
|
|
21
|
+
throw Error(`Invalid area "${area}". Options: ${areaNames}`);
|
|
22
|
+
}
|
|
23
|
+
return driver;
|
|
24
|
+
};
|
|
25
|
+
const resolveKey = (key) => {
|
|
26
|
+
const deliminatorIndex = key.indexOf(":");
|
|
27
|
+
const driverArea = key.substring(0, deliminatorIndex);
|
|
28
|
+
const driverKey = key.substring(deliminatorIndex + 1);
|
|
29
|
+
if (driverKey == null)
|
|
18
30
|
throw Error(
|
|
19
|
-
|
|
31
|
+
`Storage key should be in the form of "area:key", but recieved "${key}"`
|
|
20
32
|
);
|
|
33
|
+
return {
|
|
34
|
+
driverArea,
|
|
35
|
+
driverKey,
|
|
36
|
+
driver: getDriver(driverArea)
|
|
37
|
+
};
|
|
21
38
|
};
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
const getMetaKey = (key) => key + "$";
|
|
40
|
+
const getValueOrDefault = (value, defaultValue) => value ?? defaultValue ?? null;
|
|
41
|
+
const getMetaValue = (properties) => typeof properties === "object" && !Array.isArray(properties) ? properties : {};
|
|
42
|
+
const getItem = async (driver, driverKey, opts) => {
|
|
43
|
+
const res = await driver.getItem(driverKey);
|
|
44
|
+
return getValueOrDefault(res, opts?.defaultValue);
|
|
45
|
+
};
|
|
46
|
+
const getMeta = async (driver, driverKey) => {
|
|
47
|
+
const metaKey = getMetaKey(driverKey);
|
|
48
|
+
const res = await driver.getItem(metaKey);
|
|
49
|
+
return getMetaValue(res);
|
|
50
|
+
};
|
|
51
|
+
const setItem = async (driver, driverKey, value) => {
|
|
52
|
+
await driver.setItem(driverKey, value ?? null);
|
|
53
|
+
};
|
|
54
|
+
const setMeta = async (driver, driverKey, properties) => {
|
|
55
|
+
const metaKey = getMetaKey(driverKey);
|
|
56
|
+
const existingFields = getMetaValue(await driver.getItem(metaKey));
|
|
57
|
+
const newFields = { ...existingFields };
|
|
58
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
59
|
+
if (value == null) {
|
|
60
|
+
delete newFields[key];
|
|
61
|
+
} else {
|
|
62
|
+
newFields[key] = value;
|
|
63
|
+
}
|
|
27
64
|
});
|
|
65
|
+
await driver.setItem(metaKey, newFields);
|
|
28
66
|
};
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
const removeItem = async (driver, driverKey, opts) => {
|
|
68
|
+
await driver.removeItem(driverKey);
|
|
69
|
+
if (opts?.removeMeta) {
|
|
70
|
+
const metaKey = getMetaKey(driverKey);
|
|
71
|
+
await driver.removeItem(metaKey);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const removeMeta = async (driver, driverKey, properties) => {
|
|
75
|
+
const metaKey = getMetaKey(driverKey);
|
|
76
|
+
if (properties == null) {
|
|
77
|
+
await driver.removeItem(metaKey);
|
|
78
|
+
} else {
|
|
79
|
+
const newFields = getMetaValue(await driver.getItem(metaKey));
|
|
80
|
+
[properties].flat().forEach((field) => delete newFields[field]);
|
|
81
|
+
await driver.setItem(metaKey, newFields);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const watch = (driver, driverKey, cb) => {
|
|
85
|
+
return driver.watch(driverKey, cb);
|
|
86
|
+
};
|
|
87
|
+
const storage2 = {
|
|
88
|
+
getItem: async (key, opts) => {
|
|
89
|
+
const { driver, driverKey } = resolveKey(key);
|
|
90
|
+
return await getItem(driver, driverKey, opts);
|
|
91
|
+
},
|
|
92
|
+
getItems: async (keys) => {
|
|
93
|
+
const areaToKeyMap = /* @__PURE__ */ new Map();
|
|
94
|
+
const keyToOptsMap = /* @__PURE__ */ new Map();
|
|
95
|
+
keys.forEach((key) => {
|
|
96
|
+
let keyStr;
|
|
97
|
+
let opts;
|
|
98
|
+
if (typeof key === "string") {
|
|
99
|
+
keyStr = key;
|
|
100
|
+
} else {
|
|
101
|
+
keyStr = key.key;
|
|
102
|
+
opts = key.options;
|
|
103
|
+
}
|
|
104
|
+
const { driverArea, driverKey } = resolveKey(keyStr);
|
|
105
|
+
const keys2 = areaToKeyMap.get(driverArea) ?? [];
|
|
106
|
+
areaToKeyMap.set(driverArea, keys2.concat(driverKey));
|
|
107
|
+
keyToOptsMap.set(keyStr, opts);
|
|
108
|
+
});
|
|
109
|
+
const results = await Promise.all(
|
|
110
|
+
Array.from(areaToKeyMap.entries()).map(async ([driverArea, keys2]) => {
|
|
111
|
+
const driverResults = await drivers[driverArea].getItems(keys2);
|
|
112
|
+
return driverResults.map((driverResult) => {
|
|
113
|
+
const key = `${driverArea}:${driverResult.key}`;
|
|
114
|
+
const value = getValueOrDefault(
|
|
115
|
+
driverResult.value,
|
|
116
|
+
keyToOptsMap.get(key)?.defaultValue
|
|
117
|
+
);
|
|
118
|
+
return { key, value };
|
|
119
|
+
});
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
return results.flat();
|
|
123
|
+
},
|
|
124
|
+
getMeta: async (key) => {
|
|
125
|
+
const { driver, driverKey } = resolveKey(key);
|
|
126
|
+
return await getMeta(driver, driverKey);
|
|
127
|
+
},
|
|
128
|
+
setItem: async (key, value) => {
|
|
129
|
+
const { driver, driverKey } = resolveKey(key);
|
|
130
|
+
await setItem(driver, driverKey, value);
|
|
131
|
+
},
|
|
132
|
+
setItems: async (values) => {
|
|
133
|
+
const areaToKeyValueMap = /* @__PURE__ */ new Map();
|
|
134
|
+
values.forEach(({ key, value }) => {
|
|
135
|
+
const { driverArea, driverKey } = resolveKey(key);
|
|
136
|
+
const values2 = areaToKeyValueMap.get(driverArea) ?? [];
|
|
137
|
+
areaToKeyValueMap.set(
|
|
138
|
+
driverArea,
|
|
139
|
+
values2.concat({ key: driverKey, value })
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
await Promise.all(
|
|
143
|
+
Array.from(areaToKeyValueMap.entries()).map(
|
|
144
|
+
async ([driverArea, values2]) => {
|
|
145
|
+
const driver = getDriver(driverArea);
|
|
146
|
+
await driver.setItems(values2);
|
|
147
|
+
}
|
|
148
|
+
)
|
|
46
149
|
);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
async
|
|
53
|
-
|
|
54
|
-
await
|
|
55
|
-
},
|
|
56
|
-
async
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
150
|
+
},
|
|
151
|
+
setMeta: async (key, properties) => {
|
|
152
|
+
const { driver, driverKey } = resolveKey(key);
|
|
153
|
+
await setMeta(driver, driverKey, properties);
|
|
154
|
+
},
|
|
155
|
+
removeItem: async (key, opts) => {
|
|
156
|
+
const { driver, driverKey } = resolveKey(key);
|
|
157
|
+
await removeItem(driver, driverKey, opts);
|
|
158
|
+
},
|
|
159
|
+
removeItems: async (keys) => {
|
|
160
|
+
const areaToKeysMap = /* @__PURE__ */ new Map();
|
|
161
|
+
keys.forEach((key) => {
|
|
162
|
+
let keyStr;
|
|
163
|
+
let opts;
|
|
164
|
+
if (typeof key === "string") {
|
|
165
|
+
keyStr = key;
|
|
166
|
+
} else {
|
|
167
|
+
keyStr = key.key;
|
|
168
|
+
opts = key.options;
|
|
169
|
+
}
|
|
170
|
+
const { driverArea, driverKey } = resolveKey(keyStr);
|
|
171
|
+
const areaKeys = areaToKeysMap.get(driverArea) ?? [];
|
|
172
|
+
areaKeys.push(driverKey);
|
|
173
|
+
if (opts?.removeMeta) {
|
|
174
|
+
areaKeys.push(getMetaKey(driverKey));
|
|
175
|
+
}
|
|
176
|
+
areaToKeysMap.set(driverArea, areaKeys);
|
|
177
|
+
});
|
|
178
|
+
await Promise.all(
|
|
179
|
+
Array.from(areaToKeysMap.entries()).map(async ([driverArea, keys2]) => {
|
|
180
|
+
const driver = getDriver(driverArea);
|
|
181
|
+
await driver.removeItems(keys2);
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
},
|
|
185
|
+
removeMeta: async (key, properties) => {
|
|
186
|
+
const { driver, driverKey } = resolveKey(key);
|
|
187
|
+
await removeMeta(driver, driverKey, properties);
|
|
188
|
+
},
|
|
189
|
+
snapshot: async (base, opts) => {
|
|
190
|
+
const driver = getDriver(base);
|
|
191
|
+
const data = await driver.snapshot();
|
|
192
|
+
opts?.excludeKeys?.forEach((key) => {
|
|
193
|
+
delete data[key];
|
|
194
|
+
delete data[getMetaKey(key)];
|
|
195
|
+
});
|
|
196
|
+
return data;
|
|
197
|
+
},
|
|
198
|
+
restoreSnapshot: async (base, data) => {
|
|
199
|
+
const driver = getDriver(base);
|
|
200
|
+
await driver.restoreSnapshot(data);
|
|
201
|
+
},
|
|
202
|
+
watch: (key, cb) => {
|
|
203
|
+
const { driver, driverKey } = resolveKey(key);
|
|
204
|
+
return watch(driver, driverKey, cb);
|
|
205
|
+
},
|
|
206
|
+
unwatch() {
|
|
207
|
+
Object.values(drivers).forEach((driver) => {
|
|
208
|
+
driver.unwatch();
|
|
209
|
+
});
|
|
210
|
+
},
|
|
211
|
+
defineItem: (key, opts) => {
|
|
212
|
+
const { driver, driverKey } = resolveKey(key);
|
|
213
|
+
const { version: targetVersion = 1, migrations = {} } = opts ?? {};
|
|
214
|
+
if (targetVersion < 1) {
|
|
215
|
+
throw Error(
|
|
216
|
+
"Storage item version cannot be less than 1. Initial versions should be set to 1, not 0."
|
|
83
217
|
);
|
|
84
218
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
219
|
+
const runMigrations = async () => {
|
|
220
|
+
const [value, meta] = await Promise.all([
|
|
221
|
+
// TODO: Optimize with getItems
|
|
222
|
+
getItem(driver, driverKey, void 0),
|
|
223
|
+
getMeta(driver, driverKey)
|
|
224
|
+
]);
|
|
225
|
+
if (value == null)
|
|
226
|
+
return;
|
|
227
|
+
const currentVersion = meta.v ?? 1;
|
|
228
|
+
if (currentVersion > targetVersion) {
|
|
229
|
+
throw Error(
|
|
230
|
+
`[wxt/storage] Migration ignored for "${key}", version downgrade detected (${currentVersion} -> ${targetVersion})`
|
|
90
231
|
);
|
|
91
232
|
}
|
|
233
|
+
const migrationsToRun = Array.from(
|
|
234
|
+
{ length: targetVersion - currentVersion },
|
|
235
|
+
(_, i) => currentVersion + i + 1
|
|
236
|
+
);
|
|
237
|
+
let migratedValue = value;
|
|
238
|
+
for (const migrateToVersion of migrationsToRun) {
|
|
239
|
+
migratedValue = await migrations?.[migrateToVersion]?.(migratedValue) ?? migratedValue;
|
|
240
|
+
}
|
|
241
|
+
await Promise.all([
|
|
242
|
+
// TODO: Optimize with `setItem`
|
|
243
|
+
setItem(driver, driverKey, migratedValue),
|
|
244
|
+
setMeta(driver, driverKey, { v: targetVersion })
|
|
245
|
+
]);
|
|
246
|
+
};
|
|
247
|
+
let _migrationsCompleted = runMigrations();
|
|
248
|
+
return {
|
|
249
|
+
_migrationsCompleted,
|
|
250
|
+
getValue: () => getItem(driver, driverKey, opts),
|
|
251
|
+
getMeta: () => getMeta(driver, driverKey),
|
|
252
|
+
setValue: (value) => setItem(driver, driverKey, value),
|
|
253
|
+
setMeta: (properties) => setMeta(driver, driverKey, properties),
|
|
254
|
+
removeValue: (opts2) => removeItem(driver, driverKey, opts2),
|
|
255
|
+
removeMeta: (properties) => removeMeta(driver, driverKey, properties),
|
|
256
|
+
watch: (cb) => watch(driver, driverKey, cb)
|
|
92
257
|
};
|
|
93
258
|
}
|
|
94
259
|
};
|
|
95
|
-
});
|
|
96
|
-
function createWebExtensionStorage() {
|
|
97
|
-
const storage2 = createStorage();
|
|
98
|
-
storage2.mount("local", webExtensionDriver({ storageArea: "local" }));
|
|
99
|
-
storage2.mount("session", webExtensionDriver({ storageArea: "session" }));
|
|
100
|
-
storage2.mount("sync", webExtensionDriver({ storageArea: "sync" }));
|
|
101
|
-
storage2.mount("managed", webExtensionDriver({ storageArea: "managed" }));
|
|
102
260
|
return storage2;
|
|
103
261
|
}
|
|
104
|
-
|
|
262
|
+
function createDriver(storageArea) {
|
|
263
|
+
const getStorageArea = () => {
|
|
264
|
+
if (browser.storage == null)
|
|
265
|
+
throw Error(
|
|
266
|
+
"You must add the 'storage' permission to your manifest to use 'wxt/storage'"
|
|
267
|
+
);
|
|
268
|
+
return browser.storage[storageArea];
|
|
269
|
+
};
|
|
270
|
+
const watchListeners = /* @__PURE__ */ new Set();
|
|
271
|
+
return {
|
|
272
|
+
getItem: async (key) => {
|
|
273
|
+
const res = await getStorageArea().get(key);
|
|
274
|
+
return res[key];
|
|
275
|
+
},
|
|
276
|
+
getItems: async (keys) => {
|
|
277
|
+
const result = await getStorageArea().get(keys);
|
|
278
|
+
return keys.map((key) => ({ key, value: result[key] ?? null }));
|
|
279
|
+
},
|
|
280
|
+
setItem: async (key, value) => {
|
|
281
|
+
if (value == null) {
|
|
282
|
+
await getStorageArea().remove(key);
|
|
283
|
+
} else {
|
|
284
|
+
await getStorageArea().set({ [key]: value });
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
setItems: async (values) => {
|
|
288
|
+
const map = values.reduce(
|
|
289
|
+
(map2, { key, value }) => {
|
|
290
|
+
map2[key] = value;
|
|
291
|
+
return map2;
|
|
292
|
+
},
|
|
293
|
+
{}
|
|
294
|
+
);
|
|
295
|
+
await getStorageArea().set(map);
|
|
296
|
+
},
|
|
297
|
+
removeItem: async (key) => {
|
|
298
|
+
await getStorageArea().remove(key);
|
|
299
|
+
},
|
|
300
|
+
removeItems: async (keys) => {
|
|
301
|
+
await getStorageArea().remove(keys);
|
|
302
|
+
},
|
|
303
|
+
snapshot: async () => {
|
|
304
|
+
return await getStorageArea().get();
|
|
305
|
+
},
|
|
306
|
+
restoreSnapshot: async (data) => {
|
|
307
|
+
await getStorageArea().set(data);
|
|
308
|
+
},
|
|
309
|
+
watch(key, cb) {
|
|
310
|
+
const listener = (changes) => {
|
|
311
|
+
const change = changes[key];
|
|
312
|
+
if (change == null)
|
|
313
|
+
return;
|
|
314
|
+
if (dequal(change.newValue, change.oldValue))
|
|
315
|
+
return;
|
|
316
|
+
cb(change.newValue ?? null, change.oldValue ?? null);
|
|
317
|
+
};
|
|
318
|
+
getStorageArea().onChanged.addListener(listener);
|
|
319
|
+
watchListeners.add(listener);
|
|
320
|
+
return () => {
|
|
321
|
+
getStorageArea().onChanged.removeListener(listener);
|
|
322
|
+
watchListeners.delete(listener);
|
|
323
|
+
};
|
|
324
|
+
},
|
|
325
|
+
unwatch() {
|
|
326
|
+
watchListeners.forEach((listener) => {
|
|
327
|
+
getStorageArea().onChanged.removeListener(listener);
|
|
328
|
+
});
|
|
329
|
+
watchListeners.clear();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
105
333
|
export {
|
|
106
|
-
storage
|
|
107
|
-
webExtensionDriver
|
|
334
|
+
storage
|
|
108
335
|
};
|
package/dist/testing.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wxt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.1-alpha1",
|
|
5
5
|
"description": "Next gen framework for developing web extensions",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=18",
|
|
@@ -76,6 +76,9 @@
|
|
|
76
76
|
"types": "./dist/storage.d.cts",
|
|
77
77
|
"default": "./dist/storage.cjs"
|
|
78
78
|
}
|
|
79
|
+
},
|
|
80
|
+
"./vite-builder-env": {
|
|
81
|
+
"types": "./dist/vite-builder-env.d.ts"
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
"dependencies": {
|
|
@@ -89,6 +92,7 @@
|
|
|
89
92
|
"chokidar": "^3.5.3",
|
|
90
93
|
"consola": "^3.2.3",
|
|
91
94
|
"defu": "^6.1.3",
|
|
95
|
+
"dequal": "^2.0.3",
|
|
92
96
|
"esbuild": "^0.19.5",
|
|
93
97
|
"fast-glob": "^3.3.1",
|
|
94
98
|
"filesize": "^10.0.8",
|
|
@@ -107,7 +111,6 @@
|
|
|
107
111
|
"prompts": "^2.4.2",
|
|
108
112
|
"rollup-plugin-visualizer": "^5.9.2",
|
|
109
113
|
"unimport": "^3.4.0",
|
|
110
|
-
"unstorage": "^1.9.0",
|
|
111
114
|
"vite": "^5.0.0",
|
|
112
115
|
"web-ext-run": "^0.1.0",
|
|
113
116
|
"webextension-polyfill": "^0.10.0",
|