mirror of
https://github.com/unjs/unstorage.git
synced 2026-01-10 13:08:09 -05:00
Merge branch 'main' into feat/azure-authentication
This commit is contained in:
6
.github/workflows/autofix.yml
vendored
6
.github/workflows/autofix.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: corepack enable
|
||||
- run: npm i -fg corepack && corepack enable
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "pnpm"
|
||||
- run: pnpm install
|
||||
- run: pnpm run gen-drivers
|
||||
@@ -24,4 +24,4 @@ jobs:
|
||||
run: pnpm run lint:fix
|
||||
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef
|
||||
with:
|
||||
commit-message: "chore: apply automated lint fixes"
|
||||
commit-message: "chore: apply automated updates"
|
||||
|
||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: corepack enable
|
||||
- run: npm i -fg corepack && corepack enable
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: "pnpm"
|
||||
- uses: denoland/setup-deno@v2
|
||||
with:
|
||||
|
||||
@@ -10,7 +10,7 @@ icon: simple-icons:planetscale
|
||||
|
||||
**Driver name:** `planetscale`
|
||||
|
||||
::read-more{to="https://docs.microsoft.com/en-us/azure/key-vault/secrets/about-secrets"}
|
||||
::read-more{to="https://planetscale.com/"}
|
||||
Learn more about PlanetScale.
|
||||
::
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ const storage = createStorage({
|
||||
});
|
||||
```
|
||||
|
||||
Usage with Redis cluster (e.g. AWS ElastiCache or Azure Redis Cache):
|
||||
Usage with a Redis cluster (e.g. AWS ElastiCache or Azure Redis Cache):
|
||||
|
||||
⚠️ If you connect to a cluster, you have to use `hastags` as prefix to avoid the redis error `CROSSSLOT Keys in request don't hash to the same slot`. This means, the prefix has to be surrounded by curly braces, which forces the keys into the same hash slot.
|
||||
⚠️ If you connect to a cluster, you have to use [`hashtags`](https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/#hash-tags) as the prefix to avoid the Redis error `CROSSSLOT Keys in request don't hash to the same slot`. This means the prefix has to be surrounded by curly braces, which forces the keys into the same hash slot. You can read more [here](https://redis.io/blog/redis-clustering-best-practices-with-keys/).
|
||||
|
||||
```js
|
||||
const storage = createStorage({
|
||||
@@ -65,7 +65,7 @@ const storage = createStorage({
|
||||
|
||||
**Options:**
|
||||
|
||||
- `base`: Optional prefix to use for all keys. Can be used for namespacing. Has to be used as hastag prefix for redis cluster mode.
|
||||
- `base`: Optional prefix to use for all keys. Can be used for namespacing. Has to be used as a hashtag prefix for redis cluster mode.
|
||||
- `url`: Url to use for connecting to redis. Takes precedence over `host` option. Has the format `redis://<REDIS_USER>:<REDIS_PASSWORD>@<REDIS_HOST>:<REDIS_PORT>`
|
||||
- `cluster`: List of redis nodes to use for cluster mode. Takes precedence over `url` and `host` options.
|
||||
- `clusterOptions`: Options to use for cluster mode.
|
||||
|
||||
62
package.json
62
package.json
@@ -45,11 +45,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": "^3.1.3",
|
||||
"chokidar": "^3.6.0",
|
||||
"chokidar": "^4.0.3",
|
||||
"destr": "^2.0.3",
|
||||
"h3": "^1.13.1",
|
||||
"h3": "^1.15.0",
|
||||
"lru-cache": "^10.4.3",
|
||||
"node-fetch-native": "^1.6.4",
|
||||
"node-fetch-native": "^1.6.6",
|
||||
"ofetch": "^1.4.1",
|
||||
"ufo": "^1.5.4"
|
||||
},
|
||||
@@ -57,53 +57,53 @@
|
||||
"@azure/app-configuration": "^1.8.0",
|
||||
"@azure/cosmos": "^4.2.0",
|
||||
"@azure/data-tables": "^13.3.0",
|
||||
"@azure/identity": "^4.6.0",
|
||||
"@azure/identity": "^4.7.0",
|
||||
"@azure/keyvault-secrets": "^4.9.0",
|
||||
"@azure/storage-blob": "^12.26.0",
|
||||
"@capacitor/preferences": "^6.0.3",
|
||||
"@cloudflare/workers-types": "^4.20250109.0",
|
||||
"@capacitor/preferences": "^7.0.0",
|
||||
"@cloudflare/workers-types": "^4.20250214.0",
|
||||
"@deno/kv": "^0.9.0",
|
||||
"@electric-sql/pglite": "^0.2.15",
|
||||
"@electric-sql/pglite": "^0.2.17",
|
||||
"@libsql/client": "^0.14.0",
|
||||
"@netlify/blobs": "^8.1.0",
|
||||
"@netlify/blobs": "^8.1.1",
|
||||
"@planetscale/database": "^1.19.0",
|
||||
"@types/deno": "^2.0.0",
|
||||
"@types/deno": "^2.2.0",
|
||||
"@types/ioredis-mock": "^8.2.5",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^22.10.7",
|
||||
"@upstash/redis": "^1.34.3",
|
||||
"@types/node": "^22.13.4",
|
||||
"@upstash/redis": "^1.34.4",
|
||||
"@vercel/blob": "^0.27.1",
|
||||
"@vercel/kv": "^3.0.0",
|
||||
"@vitest/coverage-v8": "^2.1.8",
|
||||
"@vitest/coverage-v8": "^3.0.6",
|
||||
"aws4fetch": "^1.0.20",
|
||||
"azurite": "^3.33.0",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"changelogen": "^0.5.7",
|
||||
"citty": "^0.1.6",
|
||||
"db0": "^0.2.1",
|
||||
"eslint": "^9.18.0",
|
||||
"db0": "^0.2.4",
|
||||
"eslint": "^9.20.1",
|
||||
"eslint-config-unjs": "^0.4.2",
|
||||
"fake-indexeddb": "^6.0.0",
|
||||
"get-port-please": "^3.1.2",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"ioredis": "^5.4.2",
|
||||
"ioredis": "^5.5.0",
|
||||
"ioredis-mock": "^8.9.0",
|
||||
"jiti": "^2.4.2",
|
||||
"jsdom": "^25.0.1",
|
||||
"jsdom": "^26.0.0",
|
||||
"listhen": "^1.9.0",
|
||||
"mitata": "^1.0.31",
|
||||
"mitata": "^1.0.34",
|
||||
"mlly": "^1.7.4",
|
||||
"mongodb": "^6.12.0",
|
||||
"mongodb-memory-server": "^10.1.3",
|
||||
"prettier": "^3.4.2",
|
||||
"mongodb": "^6.13.1",
|
||||
"mongodb-memory-server": "^10.1.4",
|
||||
"prettier": "^3.5.1",
|
||||
"scule": "^1.3.0",
|
||||
"types-cloudflare-worker": "^1.2.0",
|
||||
"typescript": "^5.7.3",
|
||||
"unbuild": "^3.3.1",
|
||||
"uploadthing": "^7.4.4",
|
||||
"vite": "^6.0.7",
|
||||
"vitest": "^2.1.8",
|
||||
"wrangler": "^3.101.0"
|
||||
"uploadthing": "^7.5.2",
|
||||
"vite": "^6.1.1",
|
||||
"vitest": "^3.0.6",
|
||||
"wrangler": "^3.109.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@azure/app-configuration": "^1.8.0",
|
||||
@@ -181,5 +181,17 @@
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@9.15.4"
|
||||
"packageManager": "pnpm@10.4.1",
|
||||
"pnpm": {
|
||||
"ignoredBuiltDependencies": [
|
||||
"@parcel/watcher",
|
||||
"sharp",
|
||||
"workerd"
|
||||
],
|
||||
"onlyBuiltDependencies": [
|
||||
"better-sqlite3",
|
||||
"esbuild",
|
||||
"mongodb-memory-server"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
4835
pnpm-lock.yaml
generated
4835
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,7 @@
|
||||
import { existsSync, promises as fsp, Stats } from "node:fs";
|
||||
import { resolve, relative, join } from "node:path";
|
||||
import {
|
||||
FSWatcher,
|
||||
type WatchOptions as ChokidarOptions,
|
||||
watch,
|
||||
} from "chokidar";
|
||||
import { FSWatcher, type ChokidarOptions, watch } from "chokidar";
|
||||
import anymatch from "anymatch";
|
||||
import { createError, createRequiredError, defineDriver } from "./utils";
|
||||
import {
|
||||
readFile,
|
||||
@@ -13,7 +10,6 @@ import {
|
||||
rmRecursive,
|
||||
unlink,
|
||||
} from "./utils/node-fs";
|
||||
import anymatch from "anymatch";
|
||||
|
||||
export interface FSStorageOptions {
|
||||
base?: string;
|
||||
@@ -27,16 +23,17 @@ const PATH_TRAVERSE_RE = /\.\.:|\.\.$/;
|
||||
|
||||
const DRIVER_NAME = "fs";
|
||||
|
||||
export default defineDriver((opts: FSStorageOptions = {}) => {
|
||||
if (!opts.base) {
|
||||
export default defineDriver((userOptions: FSStorageOptions = {}) => {
|
||||
if (!userOptions.base) {
|
||||
throw createRequiredError(DRIVER_NAME, "base");
|
||||
}
|
||||
|
||||
if (!opts.ignore) {
|
||||
opts.ignore = ["**/node_modules/**", "**/.git/**"];
|
||||
}
|
||||
const base = resolve(userOptions.base);
|
||||
|
||||
const ignore = anymatch(
|
||||
userOptions.ignore || ["**/node_modules/**", "**/.git/**"]
|
||||
);
|
||||
|
||||
opts.base = resolve(opts.base);
|
||||
const r = (key: string) => {
|
||||
if (PATH_TRAVERSE_RE.test(key)) {
|
||||
throw createError(
|
||||
@@ -44,7 +41,7 @@ export default defineDriver((opts: FSStorageOptions = {}) => {
|
||||
`Invalid key: ${JSON.stringify(key)}. It should not contain .. segments`
|
||||
);
|
||||
}
|
||||
const resolved = join(opts.base!, key.replace(/:/g, "/"));
|
||||
const resolved = join(base, key.replace(/:/g, "/"));
|
||||
return resolved;
|
||||
};
|
||||
|
||||
@@ -58,7 +55,7 @@ export default defineDriver((opts: FSStorageOptions = {}) => {
|
||||
|
||||
return {
|
||||
name: DRIVER_NAME,
|
||||
options: opts,
|
||||
options: userOptions,
|
||||
flags: {
|
||||
maxDepth: true,
|
||||
},
|
||||
@@ -78,32 +75,28 @@ export default defineDriver((opts: FSStorageOptions = {}) => {
|
||||
return { atime, mtime, size, birthtime, ctime };
|
||||
},
|
||||
setItem(key, value) {
|
||||
if (opts.readOnly) {
|
||||
if (userOptions.readOnly) {
|
||||
return;
|
||||
}
|
||||
return writeFile(r(key), value, "utf8");
|
||||
},
|
||||
setItemRaw(key, value) {
|
||||
if (opts.readOnly) {
|
||||
if (userOptions.readOnly) {
|
||||
return;
|
||||
}
|
||||
return writeFile(r(key), value);
|
||||
},
|
||||
removeItem(key) {
|
||||
if (opts.readOnly) {
|
||||
if (userOptions.readOnly) {
|
||||
return;
|
||||
}
|
||||
return unlink(r(key));
|
||||
},
|
||||
getKeys(_base, topts) {
|
||||
return readdirRecursive(
|
||||
r("."),
|
||||
anymatch(opts.ignore || []),
|
||||
topts?.maxDepth
|
||||
);
|
||||
return readdirRecursive(r("."), ignore, topts?.maxDepth);
|
||||
},
|
||||
async clear() {
|
||||
if (opts.readOnly || opts.noClear) {
|
||||
if (userOptions.readOnly || userOptions.noClear) {
|
||||
return;
|
||||
}
|
||||
await rmRecursive(r("."));
|
||||
@@ -118,17 +111,26 @@ export default defineDriver((opts: FSStorageOptions = {}) => {
|
||||
return _unwatch;
|
||||
}
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
_watcher = watch(opts.base!, {
|
||||
const watchOptions: ChokidarOptions = {
|
||||
ignoreInitial: true,
|
||||
ignored: opts.ignore,
|
||||
...opts.watchOptions,
|
||||
})
|
||||
...userOptions.watchOptions,
|
||||
};
|
||||
if (!watchOptions.ignored) {
|
||||
watchOptions.ignored = [];
|
||||
} else if (Array.isArray(watchOptions.ignored)) {
|
||||
watchOptions.ignored = [...watchOptions.ignored];
|
||||
} else {
|
||||
watchOptions.ignored = [watchOptions.ignored];
|
||||
}
|
||||
watchOptions.ignored.push(ignore);
|
||||
|
||||
_watcher = watch(base, watchOptions)
|
||||
.on("ready", () => {
|
||||
resolve();
|
||||
})
|
||||
.on("error", reject)
|
||||
.on("all", (eventName, path) => {
|
||||
path = relative(opts.base!, path);
|
||||
path = relative(base, path);
|
||||
if (eventName === "change" || eventName === "add") {
|
||||
callback("update", path);
|
||||
} else if (eventName === "unlink") {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "preserve",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleDetection": "force",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
Reference in New Issue
Block a user