initial commit
This commit is contained in:
21
node_modules/unstorage/LICENSE
generated
vendored
Normal file
21
node_modules/unstorage/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Pooya Parsa <pooya@pi0.io>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
641
node_modules/unstorage/README.md
generated
vendored
Normal file
641
node_modules/unstorage/README.md
generated
vendored
Normal file
@@ -0,0 +1,641 @@
|
||||
# unstorage
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![Github Actions][github-actions-src]][github-actions-href]
|
||||
[![Codecov][codecov-src]][codecov-href]
|
||||
[![bundle][bundle-src]][bundle-href]
|
||||
|
||||
> 🌍 💾 Universal Storage Layer
|
||||
|
||||
|
||||
**Why ❓**
|
||||
|
||||
Typically, we choose one or more data storages based on our use-cases like a filesystem, a database like Redis, Mongo, or LocalStorage for browsers but it will soon start to be lots of trouble for supporting and combining more than one or switching between them. For javascript library authors, this usually means they have to decide how many platforms they support and implement storage for each.
|
||||
|
||||
💡 Unstorage solution is a unified and powerful Key-Value (KV) interface that allows combining drivers that are either built-in or can be implemented via a super simple interface and adding conventional features like mounting, watching, and working with metadata.
|
||||
|
||||
Comparing to similar solutions like [localforage](https://localforage.github.io/localForage/), unstorage core is almost 6x smaller (28.9 kB vs 4.7 kB), using modern ESM/Typescript/Async syntax and many more features to be used universally.
|
||||
|
||||
<br>
|
||||
✔️ Works in all environments (Browser, NodeJS, and Workers) <br>
|
||||
✔️ Multiple built-in drivers (Memory, FS, LocalStorage, HTTP, Redis) <br>
|
||||
✔️ Asynchronous API <br>
|
||||
✔️ Unix-style driver mounting to combine storages<br>
|
||||
✔️ Default in-memory storage <br>
|
||||
✔️ Tree-shakable utils and tiny core <br>
|
||||
✔️ Driver native and user provided metadata <br>
|
||||
✔️ Native aware value serialization and deserialization <br>
|
||||
✔️ Restore initial state (hydration) <br>
|
||||
✔️ State snapshot <br>
|
||||
✔️ Driver agnostic watcher <br>
|
||||
✔️ HTTP Storage server (cli and programmatic) <br>
|
||||
✔️ Namespaced storage <br>
|
||||
✔️ Overlay storage (copy-on-write) <br>
|
||||
<br>
|
||||
🚧 Virtual `fs` interface <br>
|
||||
🚧 Cached storage <br>
|
||||
🚧 More drivers: MongoDB, S3 and IndexedDB<br>
|
||||
<br>
|
||||
|
||||
**📚 Table of Contents**
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Storage Interface](#storage-interface)
|
||||
- [`storage.hasItem(key)`](#storagehasitemkey)
|
||||
- [`storage.getItem(key)`](#storagegetitemkey)
|
||||
- [`storage.setItem(key, value)`](#storagesetitemkey-value)
|
||||
- [`storage.removeItem(key, removeMeta = true)`](#storageremoveitemkey-removemeta--true)
|
||||
- [`storage.getMeta(key, nativeOnly?)`](#storagegetmetakey-nativeonly)
|
||||
- [`storage.setMeta(key)`](#storagesetmetakey)
|
||||
- [`storage.removeMeta(key)`](#storageremovemetakey)
|
||||
- [`storage.getKeys(base?)`](#storagegetkeysbase)
|
||||
- [`storage.clear(base?)`](#storageclearbase)
|
||||
- [`storage.dispose()`](#storagedispose)
|
||||
- [`storage.mount(mountpoint, driver)`](#storagemountmountpoint-driver)
|
||||
- [`storage.unmount(mountpoint, dispose = true)`](#storageunmountmountpoint-dispose--true)
|
||||
- [`storage.watch(callback)`](#storagewatchcallback)
|
||||
- [`storage.unwatch()`](#storageunwatch)
|
||||
- [Utils](#utils)
|
||||
- [`snapshot(storage, base?)`](#snapshotstorage-base)
|
||||
- [`restoreSnapshot(storage, data, base?)`](#restoresnapshotstorage-data-base)
|
||||
- [`prefixStorage(storage, data, base?)`](#prefixstoragestorage-data-base)
|
||||
- [Storage Server](#storage-server)
|
||||
- [Drivers](#drivers)
|
||||
- [`fs` (node)](#fs-node)
|
||||
- [`localStorage` (browser)](#localstorage-browser)
|
||||
- [`memory` (universal)](#memory-universal)
|
||||
- [`overlay` (universal)](#overlay-universal)
|
||||
- [`http` (universal)](#http-universal)
|
||||
- [`redis`](#redis)
|
||||
- [`cloudflare-kv-http`](#cloudflare-kv-http)
|
||||
- [`cloudflare-kv-binding`](#cloudflare-kv-binding)
|
||||
- [`github`](#github)
|
||||
- [Making custom drivers](#making-custom-drivers)
|
||||
- [Contribution](#contribution)
|
||||
- [License](#license)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## Usage
|
||||
|
||||
Install `unstorage` npm package:
|
||||
|
||||
```sh
|
||||
yarn add unstorage
|
||||
# or
|
||||
npm i unstorage
|
||||
```
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
|
||||
const storage = createStorage(/* opts */)
|
||||
|
||||
await storage.getItem('foo:bar') // or storage.getItem('/foo/bar')
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `driver`: Default driver (using memory if not provided)
|
||||
|
||||
## Storage Interface
|
||||
|
||||
### `storage.hasItem(key)`
|
||||
|
||||
Checks if storage contains a key. Resolves to either `true` or `false`.
|
||||
|
||||
```js
|
||||
await storage.hasItem('foo:bar')
|
||||
```
|
||||
|
||||
### `storage.getItem(key)`
|
||||
|
||||
Gets the value of a key in storage. Resolves to either `string` or `undefined`.
|
||||
|
||||
```js
|
||||
await storage.getItem('foo:bar')
|
||||
```
|
||||
|
||||
### `storage.setItem(key, value)`
|
||||
|
||||
Add/Update a value to the storage.
|
||||
|
||||
If the value is not a string, it will be stringified.
|
||||
|
||||
If value is `undefined`, it is same as calling `removeItem(key)`.
|
||||
|
||||
```js
|
||||
await storage.setItem('foo:bar', 'baz')
|
||||
```
|
||||
|
||||
### `storage.removeItem(key, removeMeta = true)`
|
||||
|
||||
Remove a value (and it's meta) from storage.
|
||||
|
||||
```js
|
||||
await storage.removeItem('foo:bar')
|
||||
```
|
||||
|
||||
### `storage.getMeta(key, nativeOnly?)`
|
||||
|
||||
Get metadata object for a specific key.
|
||||
|
||||
This data is fetched from two sources:
|
||||
- Driver native meta (like file creation time)
|
||||
- Custom meta set by `storage.setMeta` (overrides driver native meta)
|
||||
|
||||
```js
|
||||
await storage.getMeta('foo:bar') // For fs driver returns an object like { mtime, atime, size }
|
||||
```
|
||||
|
||||
### `storage.setMeta(key)`
|
||||
|
||||
Set custom meta for a specific key by adding a `$` suffix.
|
||||
|
||||
```js
|
||||
await storage.setMeta('foo:bar', { flag: 1 })
|
||||
// Same as storage.setItem('foo:bar$', { flag: 1 })
|
||||
```
|
||||
|
||||
### `storage.removeMeta(key)`
|
||||
|
||||
Remove meta for a specific key by adding a `$` suffix.
|
||||
|
||||
```js
|
||||
await storage.removeMeta('foo:bar',)
|
||||
// Same as storage.removeMeta('foo:bar$')
|
||||
```
|
||||
|
||||
### `storage.getKeys(base?)`
|
||||
|
||||
Get all keys. Returns an array of strings.
|
||||
|
||||
Meta keys (ending with `$`) will be filtered.
|
||||
|
||||
If a base is provided, only keys starting with the base will be returned also only mounts starting with base will be queried. Keys still have a full path.
|
||||
|
||||
```js
|
||||
await storage.getKeys()
|
||||
```
|
||||
|
||||
### `storage.clear(base?)`
|
||||
|
||||
Removes all stored key/values. If a base is provided, only mounts matching base will be cleared.
|
||||
|
||||
```js
|
||||
await storage.clear()
|
||||
```
|
||||
|
||||
### `storage.dispose()`
|
||||
|
||||
Disposes all mounted storages to ensure there are no open-handles left. Call it before exiting process.
|
||||
|
||||
**Note:** Dispose also clears in-memory data.
|
||||
|
||||
```js
|
||||
await storage.dispose()
|
||||
```
|
||||
|
||||
### `storage.mount(mountpoint, driver)`
|
||||
|
||||
By default, everything is stored in memory. We can mount additional storage space in a Unix-like fashion.
|
||||
|
||||
When operating with a `key` that starts with mountpoint, instead of default storage, mounted driver will be called.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import fsDriver from 'unstorage/drivers/fs'
|
||||
|
||||
// Create a storage container with default memory storage
|
||||
const storage = createStorage({})
|
||||
|
||||
storage.mount('/output', fsDriver({ base: './output' }))
|
||||
|
||||
// Writes to ./output/test file
|
||||
await storage.setItem('/output/test', 'works')
|
||||
|
||||
// Adds value to in-memory storage
|
||||
await storage.setItem('/foo', 'bar')
|
||||
```
|
||||
|
||||
### `storage.unmount(mountpoint, dispose = true)`
|
||||
|
||||
Unregisters a mountpoint. Has no effect if mountpoint is not found or is root.
|
||||
|
||||
```js
|
||||
await storage.unmount('/output')
|
||||
```
|
||||
|
||||
### `storage.watch(callback)`
|
||||
|
||||
Starts watching on all mountpoints. If driver does not supports watching, only emits even when `storage.*` methods are called.
|
||||
|
||||
```js
|
||||
const unwatch = await storage.watch((event, key) => { })
|
||||
// to stop this watcher
|
||||
await unwatch()
|
||||
```
|
||||
|
||||
### `storage.unwatch()`
|
||||
|
||||
Stop all watchers on all mountpoints.
|
||||
|
||||
```js
|
||||
await storage.unwatch()
|
||||
```
|
||||
|
||||
|
||||
## Utils
|
||||
|
||||
### `snapshot(storage, base?)`
|
||||
|
||||
Snapshot from all keys in specified base into a plain javascript object (string: string). Base is removed from keys.
|
||||
|
||||
```js
|
||||
import { snapshot } from 'unstorage'
|
||||
|
||||
const data = await snapshot(storage, '/etc')
|
||||
```
|
||||
|
||||
### `restoreSnapshot(storage, data, base?)`
|
||||
|
||||
Restore snapshot created by `snapshot()`.
|
||||
|
||||
```js
|
||||
await restoreSnapshot(storage, { 'foo:bar': 'baz' }, '/etc2')
|
||||
```
|
||||
|
||||
### `prefixStorage(storage, data, base?)`
|
||||
|
||||
Create a namespaced instance of main storage.
|
||||
|
||||
All operations are virtually prefixed. Useful to create shorcuts and limit access.
|
||||
|
||||
```js
|
||||
import { createStorage, prefixStorage } from 'unstorage'
|
||||
|
||||
const storage = createStorage()
|
||||
const assetsStorage = prefixStorage(storage, 'assets')
|
||||
|
||||
// Same as storage.setItem('assets:x', 'hello!')
|
||||
await assetsStorage.setItem('x', 'hello!')
|
||||
```
|
||||
|
||||
## Storage Server
|
||||
|
||||
We can easily expose unstorage instance to an http server to allow remote connections.
|
||||
Request url is mapped to key and method/body mapped to function. See below for supported http methods.
|
||||
|
||||
**🛡️ Security Note:** Server is unprotected by default. You need to add your own authentication/security middleware like basic authentication.
|
||||
Also consider that even with authentication, unstorage should not be exposed to untrusted users since it has no protection for abuse (DDOS, Filesystem escalation, etc)
|
||||
|
||||
**Programmatic usage:**
|
||||
|
||||
```js
|
||||
import { listen } from 'listhen'
|
||||
import { createStorage } from 'unstorage'
|
||||
import { createStorageServer } from 'unstorage/server'
|
||||
|
||||
const storage = createStorage()
|
||||
const storageServer = createStorageServer(storage)
|
||||
|
||||
// Alternatively we can use `storageServer.handle` as a middleware
|
||||
await listen(storageServer.handle)
|
||||
```
|
||||
|
||||
**Using CLI:**
|
||||
|
||||
```sh
|
||||
npx unstorage .
|
||||
```
|
||||
|
||||
**Supported HTTP Methods:**
|
||||
|
||||
- `GET`: Maps to `storage.getItem`. Returns list of keys on path if value not found.
|
||||
- `HEAD`: Maps to `storage.hasItem`. Returns 404 if not found.
|
||||
- `PUT`: Maps to `storage.setItem`. Value is read from body and returns `OK` if operation succeeded.
|
||||
- `DELETE`: Maps to `storage.removeItem`. Returns `OK` if operation succeeded.
|
||||
|
||||
## Drivers
|
||||
|
||||
### `fs` (node)
|
||||
|
||||
Maps data to the real filesystem using directory structure for nested keys. Supports watching using [chokidar](https://github.com/paulmillr/chokidar).
|
||||
|
||||
This driver implements meta for each key including `mtime` (last modified time), `atime` (last access time), and `size` (file size) using `fs.stat`.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import fsDriver from 'unstorage/drivers/fs'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: fsDriver({ base: './tmp' })
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `base`: Base directory to isolate operations on this directory
|
||||
- `ignore`: Ignore patterns for watch <!-- and key listing -->
|
||||
- `watchOptions`: Additional [chokidar](https://github.com/paulmillr/chokidar) options.
|
||||
|
||||
### `localStorage` (browser)
|
||||
|
||||
Store data in [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import localStorageDriver from 'unstorage/drivers/localstorage'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: localStorageDriver({ base: 'app:' })
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `base`: Add `${base}:` to all keys to avoid collision
|
||||
- `localStorage`: Optionally provide `localStorage` object
|
||||
- `window`: Optionally provide `window` object
|
||||
|
||||
### `memory` (universal)
|
||||
|
||||
Keeps data in memory using [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).
|
||||
|
||||
By default it is mounted to top level so it is unlikely you need to mount it again.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import memoryDriver from 'unstorage/drivers/memory'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: memoryDriver()
|
||||
})
|
||||
```
|
||||
|
||||
### `overlay` (universal)
|
||||
|
||||
This is a special driver that creates a multi-layer overlay driver.
|
||||
|
||||
All write operations happen on the top level layer while values are read from all layers.
|
||||
|
||||
When removing a key, a special value `__OVERLAY_REMOVED__` will be set on the top level layer internally.
|
||||
|
||||
In the example below, we create an in-memory overlay on top of fs. No changes will be actually written to the disk.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import overlay from 'unstorage/drivers/overlay'
|
||||
import memory from 'unstorage/drivers/memory'
|
||||
import fs from 'unstorage/drivers/fs'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: overlay({
|
||||
layers: [
|
||||
memory(),
|
||||
fs({ base: './data' })
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### `http` (universal)
|
||||
|
||||
Use a remote HTTP/HTTPS endpoint as data storage. Supports built-in [http server](#storage-server) methods.
|
||||
|
||||
This driver implements meta for each key including `mtime` (last modified time) and `status` from HTTP headers by making a `HEAD` request.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import httpDriver from 'unstorage/drivers/http'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: httpDriver({ base: 'http://cdn.com' })
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `base`: Base URL for urls
|
||||
|
||||
**Supported HTTP Methods:**
|
||||
|
||||
- `getItem`: Maps to http `GET`. Returns deserialized value if response is ok
|
||||
- `hasItem`: Maps to http `HEAD`. Returns `true` if response is ok (200)
|
||||
- `setItem`: Maps to http `PUT`. Sends serialized value using body
|
||||
- `removeItem`: Maps to `DELETE`
|
||||
- `clear`: Not supported
|
||||
|
||||
### `redis`
|
||||
|
||||
Store data in a redis storage using [ioredis](https://github.com/luin/ioredis).
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import redisDriver from 'unstorage/drivers/redis'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: redisDriver({
|
||||
base: 'storage:'
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `base`: Prefix all keys with base
|
||||
- `url`: (optional) connection string
|
||||
|
||||
See [ioredis](https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options) for all available options.
|
||||
|
||||
`lazyConnect` option is enabled by default so that connection happens on first redis operation.
|
||||
|
||||
### `cloudflare-kv-http`
|
||||
|
||||
Store data in [Cloudflare KV](https://developers.cloudflare.com/workers/learning/how-kv-works/) using the [Cloudflare API v4](https://api.cloudflare.com/).
|
||||
|
||||
You need to create a KV namespace. See [KV Bindings](https://developers.cloudflare.com/workers/runtime-apis/kv#kv-bindings) for more information.
|
||||
|
||||
**Note:** This driver uses native fetch and works universally! For using directly in a cloudflare worker environemnt, please use `cloudflare-kv-binding` driver for best performance!
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import cloudflareKVHTTPDriver from 'unstorage/drivers/cloudflare-kv-http'
|
||||
|
||||
// Using `apiToken`
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVHTTPDriver({
|
||||
accountId: 'my-account-id',
|
||||
namespaceId: 'my-kv-namespace-id',
|
||||
apiToken: 'supersecret-api-token',
|
||||
}),
|
||||
})
|
||||
|
||||
// Using `email` and `apiKey`
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVHTTPDriver({
|
||||
accountId: 'my-account-id',
|
||||
namespaceId: 'my-kv-namespace-id',
|
||||
email: 'me@example.com',
|
||||
apiKey: 'my-api-key',
|
||||
}),
|
||||
})
|
||||
|
||||
// Using `userServiceKey`
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVHTTPDriver({
|
||||
accountId: 'my-account-id',
|
||||
namespaceId: 'my-kv-namespace-id',
|
||||
userServiceKey: 'v1.0-my-service-key',
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `accountId`: Cloudflare account ID.
|
||||
- `namespaceId`: The ID of the KV namespace to target. **Note:** be sure to use the namespace's ID, and not the name or binding used in a worker environment.
|
||||
- `apiToken`: API Token generated from the [User Profile 'API Tokens' page](https://dash.cloudflare.com/profile/api-tokens).
|
||||
- `email`: Email address associated with your account. May be used along with `apiKey` to authenticate in place of `apiToken`.
|
||||
- `apiKey`: API key generated on the "My Account" page of the Cloudflare console. May be used along with `email` to authenticate in place of `apiToken`.
|
||||
- `userServiceKey`: A special Cloudflare API key good for a restricted set of endpoints. Always begins with "v1.0-", may vary in length. May be used to authenticate in place of `apiToken` or `apiKey` and `email`.
|
||||
- `apiURL`: Custom API URL. Default is `https://api.cloudflare.com`.
|
||||
|
||||
**Supported methods:**
|
||||
|
||||
- `getItem`: Maps to [Read key-value pair](https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair) `GET accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/values/:key_name`
|
||||
- `hasItem`: Maps to [Read key-value pair](https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair) `GET accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/values/:key_name`. Returns `true` if `<parsed response body>.success` is `true`.
|
||||
- `setItem`: Maps to [Write key-value pair](https://api.cloudflare.com/#workers-kv-namespace-write-key-value-pair) `PUT accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/values/:key_name`
|
||||
- `removeItem`: Maps to [Delete key-value pair](https://api.cloudflare.com/#workers-kv-namespace-delete-key-value-pair) `DELETE accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/values/:key_name`
|
||||
- `getKeys`: Maps to [List a Namespace's Keys](https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys) `GET accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/keys`
|
||||
- `clear`: Maps to [Delete key-value pair](https://api.cloudflare.com/#workers-kv-namespace-delete-multiple-key-value-pairs) `DELETE accounts/:account_identifier/storage/kv/namespaces/:namespace_identifier/bulk`
|
||||
|
||||
### `cloudflare-kv-binding`
|
||||
|
||||
Store data in [Cloudflare KV](https://developers.cloudflare.com/workers/runtime-apis/kv) and access from worker bindings.
|
||||
|
||||
**Note:** This driver only works in a cloudflare worker environment! Use `cloudflare-kv-http` for other environments.
|
||||
|
||||
You need to create and assign a KV. See [KV Bindings](https://developers.cloudflare.com/workers/runtime-apis/kv#kv-bindings) for more information.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import cloudflareKVBindingDriver from 'unstorage/drivers/cloudflare-kv-binding'
|
||||
|
||||
// Using binding name to be picked from globalThis
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVBindingDriver({ binding: 'STORAGE' })
|
||||
})
|
||||
|
||||
// Directly setting binding
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVBindingDriver({ binding: globalThis.STORAGE })
|
||||
})
|
||||
|
||||
// Using from Durable Objects and Workers using Modules Syntax
|
||||
const storage = createStorage({
|
||||
driver: cloudflareKVBindingDriver({ binding: this.env.STORAGE })
|
||||
})
|
||||
|
||||
// Using outside of Cloudflare Workers (like Node.js)
|
||||
// Use cloudflare-kv-http!
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `binding`: KV binding or name of namespace. Default is `STORAGE`.
|
||||
|
||||
### `github`
|
||||
|
||||
Map files from a remote github repository. (readonly)
|
||||
|
||||
This driver fetches all possible keys once and keep it in cache for 10 minutes. Because of github rate limit, it is highly recommanded to provide a token. It only applies to fetching keys.
|
||||
|
||||
```js
|
||||
import { createStorage } from 'unstorage'
|
||||
import githubDriver from 'unstorage/drivers/github'
|
||||
|
||||
const storage = createStorage({
|
||||
driver: githubDriver({
|
||||
repo: 'nuxt/framework',
|
||||
branch: 'main',
|
||||
dir: '/docs/content'
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- **`repo`**: Github repository. Format is `username/repo` or `org/repo`. (Required!)
|
||||
- **`token`**: Github API token. (Recommended!)
|
||||
- `branch`: Target branch. Default is `main`
|
||||
- `dir`: Use a directory as driver root.
|
||||
- `ttl`: Filenames cache revalidate time. Default is `600` seconds (10 minutes)
|
||||
- `apiURL`: Github API domain. Default is `https://api.github.com`
|
||||
- `cdnURL`: Github RAW CDN Url. Default is `https://raw.githubusercontent.com`
|
||||
|
||||
## Making custom drivers
|
||||
|
||||
It is possible to extend unstorage by creating custom drives.
|
||||
|
||||
- Keys are always normalized in `foo:bar` convention
|
||||
- Mount base is removed
|
||||
- Returning promise or direct value is optional
|
||||
- You should cleanup any open watcher and handlers in `dispose`
|
||||
- Value returned by `getItem` can be a serializable object or string
|
||||
- Having `watch` method, disables default handler for mountpoint. You are responsible to emit event on `getItem`, `setItem` and `removeItem`.
|
||||
|
||||
See [src/drivers](./src/drivers) to inspire how to implement them. Methods can
|
||||
|
||||
**Example:**
|
||||
|
||||
```js
|
||||
import { createStorage, defineDriver } from 'unstorage'
|
||||
|
||||
const myStorageDriver = defineDriver((_opts) => {
|
||||
return {
|
||||
async hasItem (key) {},
|
||||
async getItem (key) {},
|
||||
async setItem(key, value) {},
|
||||
async removeItem (key) {},
|
||||
async getKeys() {},
|
||||
async clear() {},
|
||||
async dispose() {},
|
||||
// async watch(callback) {}
|
||||
}
|
||||
})
|
||||
|
||||
const storage = createStorage({
|
||||
driver: myStorageDriver()
|
||||
})
|
||||
```
|
||||
|
||||
## Contribution
|
||||
|
||||
- Clone repository
|
||||
- Install dependencies with `yarn install`
|
||||
- Use `yarn dev` to start jest watcher verifying changes
|
||||
- Use `yarn test` before pushing to ensure all tests and lint checks passing
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
|
||||
<!-- Badges -->
|
||||
[npm-version-src]: https://img.shields.io/npm/v/unstorage?style=flat-square
|
||||
[npm-version-href]: https://npmjs.com/package/unstorage
|
||||
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/unstorage?style=flat-square
|
||||
[npm-downloads-href]: https://npmjs.com/package/unstorage
|
||||
|
||||
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/unstorage/ci/main?style=flat-square
|
||||
[github-actions-href]: https://github.com/unjs/unstorage/actions?query=workflow%3Aci
|
||||
|
||||
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/unstorage/main?style=flat-square
|
||||
[codecov-href]: https://codecov.io/gh/unjs/unstorage
|
||||
|
||||
[bundle-src]: https://img.shields.io/bundlephobia/minzip/unstorage?style=flat-square
|
||||
[bundle-href]: https://bundlephobia.com/result?p=unstorage
|
||||
68
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.cjs
generated
vendored
Normal file
68
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.cjs
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _default = (0, _utils.defineDriver)((opts = {}) => {
|
||||
const binding = getBinding(opts.binding);
|
||||
|
||||
async function getKeys(base) {
|
||||
const kvList = await binding.list(base ? {
|
||||
prefix: base
|
||||
} : void 0);
|
||||
return kvList.keys.map(key => key.name);
|
||||
}
|
||||
|
||||
return {
|
||||
async hasItem(key) {
|
||||
return (await binding.get(key)) !== null;
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
return binding.get(key);
|
||||
},
|
||||
|
||||
setItem(key, value) {
|
||||
return binding.put(key, value);
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
return binding.delete(key);
|
||||
},
|
||||
|
||||
getKeys,
|
||||
|
||||
async clear() {
|
||||
const keys = await getKeys();
|
||||
await Promise.all(keys.map(key => binding.delete(key)));
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
|
||||
function getBinding(binding = "STORAGE") {
|
||||
let bindingName = "[binding]";
|
||||
|
||||
if (typeof binding === "string") {
|
||||
bindingName = binding;
|
||||
binding = globalThis[bindingName];
|
||||
}
|
||||
|
||||
if (!binding) {
|
||||
throw new Error(`Invalid Cloudflare KV binding '${bindingName}': ${binding}`);
|
||||
}
|
||||
|
||||
for (const key of ["get", "put", "delete"]) {
|
||||
if (!(key in binding)) {
|
||||
throw new Error(`Invalid Cloudflare KV binding '${bindingName}': '${key}' key is missing`);
|
||||
}
|
||||
}
|
||||
|
||||
return binding;
|
||||
}
|
||||
6
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.d.ts
generated
vendored
Normal file
6
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/// <reference types="@cloudflare/workers-types" />
|
||||
export interface KVOptions {
|
||||
binding?: string | KVNamespace;
|
||||
}
|
||||
declare const _default: (opts?: KVOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
43
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.mjs
generated
vendored
Normal file
43
node_modules/unstorage/dist/drivers/cloudflare-kv-binding.mjs
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
export default defineDriver((opts = {}) => {
|
||||
const binding = getBinding(opts.binding);
|
||||
async function getKeys(base) {
|
||||
const kvList = await binding.list(base ? { prefix: base } : void 0);
|
||||
return kvList.keys.map((key) => key.name);
|
||||
}
|
||||
return {
|
||||
async hasItem(key) {
|
||||
return await binding.get(key) !== null;
|
||||
},
|
||||
getItem(key) {
|
||||
return binding.get(key);
|
||||
},
|
||||
setItem(key, value) {
|
||||
return binding.put(key, value);
|
||||
},
|
||||
removeItem(key) {
|
||||
return binding.delete(key);
|
||||
},
|
||||
getKeys,
|
||||
async clear() {
|
||||
const keys = await getKeys();
|
||||
await Promise.all(keys.map((key) => binding.delete(key)));
|
||||
}
|
||||
};
|
||||
});
|
||||
function getBinding(binding = "STORAGE") {
|
||||
let bindingName = "[binding]";
|
||||
if (typeof binding === "string") {
|
||||
bindingName = binding;
|
||||
binding = globalThis[bindingName];
|
||||
}
|
||||
if (!binding) {
|
||||
throw new Error(`Invalid Cloudflare KV binding '${bindingName}': ${binding}`);
|
||||
}
|
||||
for (const key of ["get", "put", "delete"]) {
|
||||
if (!(key in binding)) {
|
||||
throw new Error(`Invalid Cloudflare KV binding '${bindingName}': '${key}' key is missing`);
|
||||
}
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
165
node_modules/unstorage/dist/drivers/cloudflare-kv-http.cjs
generated
vendored
Normal file
165
node_modules/unstorage/dist/drivers/cloudflare-kv-http.cjs
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _ofetch = require("ofetch");
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
const LOG_TAG = "[unstorage] [cloudflare-http] ";
|
||||
|
||||
var _default = (0, _utils.defineDriver)(opts => {
|
||||
if (!opts.accountId) {
|
||||
throw new Error(LOG_TAG + "`accountId` is required.");
|
||||
}
|
||||
|
||||
if (!opts.namespaceId) {
|
||||
throw new Error(LOG_TAG + "`namespaceId` is required.");
|
||||
}
|
||||
|
||||
let headers;
|
||||
|
||||
if ("apiToken" in opts) {
|
||||
headers = {
|
||||
Authorization: `Bearer ${opts.apiToken}`
|
||||
};
|
||||
} else if ("userServiceKey" in opts) {
|
||||
headers = {
|
||||
"X-Auth-User-Service-Key": opts.userServiceKey
|
||||
};
|
||||
} else if (opts.email && opts.apiKey) {
|
||||
headers = {
|
||||
"X-Auth-Email": opts.email,
|
||||
"X-Auth-Key": opts.apiKey
|
||||
};
|
||||
} else {
|
||||
throw new Error(LOG_TAG + "One of the `apiToken`, `userServiceKey`, or a combination of `email` and `apiKey` is required.");
|
||||
}
|
||||
|
||||
const apiURL = opts.apiURL || "https://api.cloudflare.com";
|
||||
const baseURL = `${apiURL}/client/v4/accounts/${opts.accountId}/storage/kv/namespaces/${opts.namespaceId}`;
|
||||
|
||||
const kvFetch = _ofetch.$fetch.create({
|
||||
baseURL,
|
||||
headers
|
||||
});
|
||||
|
||||
const hasItem = async key => {
|
||||
try {
|
||||
const res = await kvFetch(`/metadata/${key}`);
|
||||
return res?.success === true;
|
||||
} catch (err) {
|
||||
if (!err.response) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (err.response.status === 404) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const getItem = async key => {
|
||||
try {
|
||||
return await kvFetch(`/values/${key}`).then(r => r.text());
|
||||
} catch (err) {
|
||||
if (!err.response) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (err.response.status === 404) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const setItem = async (key, value) => {
|
||||
return await kvFetch(`/values/${key}`, {
|
||||
method: "PUT",
|
||||
body: value
|
||||
});
|
||||
};
|
||||
|
||||
const removeItem = async key => {
|
||||
return await kvFetch(`/values/${key}`, {
|
||||
method: "DELETE"
|
||||
});
|
||||
};
|
||||
|
||||
const getKeys = async base => {
|
||||
const keys = [];
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (base) {
|
||||
params.set("prefix", base);
|
||||
}
|
||||
|
||||
const firstPage = await kvFetch("/keys", {
|
||||
params
|
||||
});
|
||||
firstPage.result.forEach(({
|
||||
name
|
||||
}) => keys.push(name));
|
||||
const cursor = firstPage.result_info.cursor;
|
||||
|
||||
if (cursor) {
|
||||
params.set("cursor", cursor);
|
||||
}
|
||||
|
||||
while (params.has("cursor")) {
|
||||
const pageResult = await kvFetch("/keys", {
|
||||
params
|
||||
});
|
||||
pageResult.result.forEach(({
|
||||
name
|
||||
}) => keys.push(name));
|
||||
const pageCursor = pageResult.result_info.cursor;
|
||||
|
||||
if (pageCursor) {
|
||||
params.set("cursor", pageCursor);
|
||||
} else {
|
||||
params.delete("cursor");
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
const clear = async () => {
|
||||
const keys = await getKeys();
|
||||
const chunks = keys.reduce((acc, key, i) => {
|
||||
if (i % 1e4 === 0) {
|
||||
acc.push([]);
|
||||
}
|
||||
|
||||
acc[acc.length - 1].push(key);
|
||||
return acc;
|
||||
}, [[]]);
|
||||
await Promise.all(chunks.map(chunk => {
|
||||
return kvFetch("/bulk", {
|
||||
method: "DELETE",
|
||||
body: {
|
||||
keys: chunk
|
||||
}
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
return {
|
||||
hasItem,
|
||||
getItem,
|
||||
setItem,
|
||||
removeItem,
|
||||
getKeys,
|
||||
clear
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
47
node_modules/unstorage/dist/drivers/cloudflare-kv-http.d.ts
generated
vendored
Normal file
47
node_modules/unstorage/dist/drivers/cloudflare-kv-http.d.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
interface KVAuthAPIToken {
|
||||
/**
|
||||
* API Token generated from the [User Profile 'API Tokens' page](https://dash.cloudflare.com/profile/api-tokens)
|
||||
* of the Cloudflare console.
|
||||
* @see https://api.cloudflare.com/#getting-started-requests
|
||||
*/
|
||||
apiToken: string;
|
||||
}
|
||||
interface KVAuthServiceKey {
|
||||
/**
|
||||
* A special Cloudflare API key good for a restricted set of endpoints.
|
||||
* Always begins with "v1.0-", may vary in length.
|
||||
* May be used to authenticate in place of `apiToken` or `apiKey` and `email`.
|
||||
* @see https://api.cloudflare.com/#getting-started-requests
|
||||
*/
|
||||
userServiceKey: string;
|
||||
}
|
||||
interface KVAuthEmailKey {
|
||||
/**
|
||||
* Email address associated with your account.
|
||||
* Should be used along with `apiKey` to authenticate in place of `apiToken`.
|
||||
*/
|
||||
email: string;
|
||||
/**
|
||||
* API key generated on the "My Account" page of the Cloudflare console.
|
||||
* Should be used along with `email` to authenticate in place of `apiToken`.
|
||||
* @see https://api.cloudflare.com/#getting-started-requests
|
||||
*/
|
||||
apiKey: string;
|
||||
}
|
||||
export declare type KVHTTPOptions = {
|
||||
/**
|
||||
* Cloudflare account ID (required)
|
||||
*/
|
||||
accountId: string;
|
||||
/**
|
||||
* The ID of the KV namespace to target (required)
|
||||
*/
|
||||
namespaceId: string;
|
||||
/**
|
||||
* The URL of the Cloudflare API.
|
||||
* @default https://api.cloudflare.com
|
||||
*/
|
||||
apiURL?: string;
|
||||
} & (KVAuthServiceKey | KVAuthAPIToken | KVAuthEmailKey);
|
||||
declare const _default: (opts?: KVHTTPOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
107
node_modules/unstorage/dist/drivers/cloudflare-kv-http.mjs
generated
vendored
Normal file
107
node_modules/unstorage/dist/drivers/cloudflare-kv-http.mjs
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
import { $fetch } from "ofetch";
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
const LOG_TAG = "[unstorage] [cloudflare-http] ";
|
||||
export default defineDriver((opts) => {
|
||||
if (!opts.accountId) {
|
||||
throw new Error(LOG_TAG + "`accountId` is required.");
|
||||
}
|
||||
if (!opts.namespaceId) {
|
||||
throw new Error(LOG_TAG + "`namespaceId` is required.");
|
||||
}
|
||||
let headers;
|
||||
if ("apiToken" in opts) {
|
||||
headers = { Authorization: `Bearer ${opts.apiToken}` };
|
||||
} else if ("userServiceKey" in opts) {
|
||||
headers = { "X-Auth-User-Service-Key": opts.userServiceKey };
|
||||
} else if (opts.email && opts.apiKey) {
|
||||
headers = { "X-Auth-Email": opts.email, "X-Auth-Key": opts.apiKey };
|
||||
} else {
|
||||
throw new Error(
|
||||
LOG_TAG + "One of the `apiToken`, `userServiceKey`, or a combination of `email` and `apiKey` is required."
|
||||
);
|
||||
}
|
||||
const apiURL = opts.apiURL || "https://api.cloudflare.com";
|
||||
const baseURL = `${apiURL}/client/v4/accounts/${opts.accountId}/storage/kv/namespaces/${opts.namespaceId}`;
|
||||
const kvFetch = $fetch.create({ baseURL, headers });
|
||||
const hasItem = async (key) => {
|
||||
try {
|
||||
const res = await kvFetch(`/metadata/${key}`);
|
||||
return res?.success === true;
|
||||
} catch (err) {
|
||||
if (!err.response) {
|
||||
throw err;
|
||||
}
|
||||
if (err.response.status === 404) {
|
||||
return false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
const getItem = async (key) => {
|
||||
try {
|
||||
return await kvFetch(`/values/${key}`).then((r) => r.text());
|
||||
} catch (err) {
|
||||
if (!err.response) {
|
||||
throw err;
|
||||
}
|
||||
if (err.response.status === 404) {
|
||||
return null;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
const setItem = async (key, value) => {
|
||||
return await kvFetch(`/values/${key}`, { method: "PUT", body: value });
|
||||
};
|
||||
const removeItem = async (key) => {
|
||||
return await kvFetch(`/values/${key}`, { method: "DELETE" });
|
||||
};
|
||||
const getKeys = async (base) => {
|
||||
const keys = [];
|
||||
const params = new URLSearchParams();
|
||||
if (base) {
|
||||
params.set("prefix", base);
|
||||
}
|
||||
const firstPage = await kvFetch("/keys", { params });
|
||||
firstPage.result.forEach(({ name }) => keys.push(name));
|
||||
const cursor = firstPage.result_info.cursor;
|
||||
if (cursor) {
|
||||
params.set("cursor", cursor);
|
||||
}
|
||||
while (params.has("cursor")) {
|
||||
const pageResult = await kvFetch("/keys", { params });
|
||||
pageResult.result.forEach(({ name }) => keys.push(name));
|
||||
const pageCursor = pageResult.result_info.cursor;
|
||||
if (pageCursor) {
|
||||
params.set("cursor", pageCursor);
|
||||
} else {
|
||||
params.delete("cursor");
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
const clear = async () => {
|
||||
const keys = await getKeys();
|
||||
const chunks = keys.reduce((acc, key, i) => {
|
||||
if (i % 1e4 === 0) {
|
||||
acc.push([]);
|
||||
}
|
||||
acc[acc.length - 1].push(key);
|
||||
return acc;
|
||||
}, [[]]);
|
||||
await Promise.all(chunks.map((chunk) => {
|
||||
return kvFetch("/bulk", {
|
||||
method: "DELETE",
|
||||
body: { keys: chunk }
|
||||
});
|
||||
}));
|
||||
};
|
||||
return {
|
||||
hasItem,
|
||||
getItem,
|
||||
setItem,
|
||||
removeItem,
|
||||
getKeys,
|
||||
clear
|
||||
};
|
||||
});
|
||||
121
node_modules/unstorage/dist/drivers/fs.cjs
generated
vendored
Normal file
121
node_modules/unstorage/dist/drivers/fs.cjs
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _fs = require("fs");
|
||||
|
||||
var _path = require("path");
|
||||
|
||||
var _chokidar = require("chokidar");
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _nodeFs = require("./utils/node-fs.cjs");
|
||||
|
||||
var _anymatch = _interopRequireDefault(require("anymatch"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
const PATH_TRAVERSE_RE = /\.\.\:|\.\.$/;
|
||||
|
||||
var _default = (0, _utils.defineDriver)((opts = {}) => {
|
||||
if (!opts.base) {
|
||||
throw new Error("base is required");
|
||||
}
|
||||
|
||||
if (!opts.ignore) {
|
||||
opts.ignore = ["**/node_modules/**", "**/.git/**"];
|
||||
}
|
||||
|
||||
opts.base = (0, _path.resolve)(opts.base);
|
||||
|
||||
const r = key => {
|
||||
if (PATH_TRAVERSE_RE.test(key)) {
|
||||
throw new Error("[unstorage] [fs] Invalid key. It should not contain `..` segments: " + key);
|
||||
}
|
||||
|
||||
const resolved = (0, _path.join)(opts.base, key.replace(/:/g, "/"));
|
||||
return resolved;
|
||||
};
|
||||
|
||||
let _watcher;
|
||||
|
||||
return {
|
||||
hasItem(key) {
|
||||
return (0, _fs.existsSync)(r(key));
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
return (0, _nodeFs.readFile)(r(key));
|
||||
},
|
||||
|
||||
async getMeta(key) {
|
||||
const {
|
||||
atime,
|
||||
mtime,
|
||||
size
|
||||
} = await _fs.promises.stat(r(key)).catch(() => ({
|
||||
atime: void 0,
|
||||
mtime: void 0,
|
||||
size: void 0
|
||||
}));
|
||||
return {
|
||||
atime,
|
||||
mtime,
|
||||
size
|
||||
};
|
||||
},
|
||||
|
||||
setItem(key, value) {
|
||||
return (0, _nodeFs.writeFile)(r(key), value);
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
return (0, _nodeFs.unlink)(r(key));
|
||||
},
|
||||
|
||||
getKeys() {
|
||||
return (0, _nodeFs.readdirRecursive)(r("."), (0, _anymatch.default)(opts.ignore || []));
|
||||
},
|
||||
|
||||
async clear() {
|
||||
await (0, _nodeFs.rmRecursive)(r("."));
|
||||
},
|
||||
|
||||
async dispose() {
|
||||
if (_watcher) {
|
||||
await _watcher.close();
|
||||
}
|
||||
},
|
||||
|
||||
watch(callback) {
|
||||
if (_watcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise((resolve2, reject) => {
|
||||
_watcher = (0, _chokidar.watch)(opts.base, {
|
||||
ignoreInitial: true,
|
||||
ignored: opts.ignore,
|
||||
...opts.watchOptions
|
||||
}).on("ready", () => {
|
||||
resolve2(() => _watcher.close().then(() => _watcher = void 0));
|
||||
}).on("error", reject).on("all", (eventName, path) => {
|
||||
path = (0, _path.relative)(opts.base, path);
|
||||
|
||||
if (eventName === "change" || eventName === "add") {
|
||||
callback("update", path);
|
||||
} else if (eventName === "unlink") {
|
||||
callback("remove", path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
8
node_modules/unstorage/dist/drivers/fs.d.ts
generated
vendored
Normal file
8
node_modules/unstorage/dist/drivers/fs.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { WatchOptions } from 'chokidar';
|
||||
export interface FSStorageOptions {
|
||||
base?: string;
|
||||
ignore?: string[];
|
||||
watchOptions?: WatchOptions;
|
||||
}
|
||||
declare const _default: (opts?: FSStorageOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
77
node_modules/unstorage/dist/drivers/fs.mjs
generated
vendored
Normal file
77
node_modules/unstorage/dist/drivers/fs.mjs
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import { existsSync, promises as fsp } from "fs";
|
||||
import { resolve, relative, join } from "path";
|
||||
import { watch } from "chokidar";
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
import { readFile, writeFile, readdirRecursive, rmRecursive, unlink } from "./utils/node-fs.mjs";
|
||||
import anymatch from "anymatch";
|
||||
const PATH_TRAVERSE_RE = /\.\.\:|\.\.$/;
|
||||
export default defineDriver((opts = {}) => {
|
||||
if (!opts.base) {
|
||||
throw new Error("base is required");
|
||||
}
|
||||
if (!opts.ignore) {
|
||||
opts.ignore = [
|
||||
"**/node_modules/**",
|
||||
"**/.git/**"
|
||||
];
|
||||
}
|
||||
opts.base = resolve(opts.base);
|
||||
const r = (key) => {
|
||||
if (PATH_TRAVERSE_RE.test(key)) {
|
||||
throw new Error("[unstorage] [fs] Invalid key. It should not contain `..` segments: " + key);
|
||||
}
|
||||
const resolved = join(opts.base, key.replace(/:/g, "/"));
|
||||
return resolved;
|
||||
};
|
||||
let _watcher;
|
||||
return {
|
||||
hasItem(key) {
|
||||
return existsSync(r(key));
|
||||
},
|
||||
getItem(key) {
|
||||
return readFile(r(key));
|
||||
},
|
||||
async getMeta(key) {
|
||||
const { atime, mtime, size } = await fsp.stat(r(key)).catch(() => ({ atime: void 0, mtime: void 0, size: void 0 }));
|
||||
return { atime, mtime, size };
|
||||
},
|
||||
setItem(key, value) {
|
||||
return writeFile(r(key), value);
|
||||
},
|
||||
removeItem(key) {
|
||||
return unlink(r(key));
|
||||
},
|
||||
getKeys() {
|
||||
return readdirRecursive(r("."), anymatch(opts.ignore || []));
|
||||
},
|
||||
async clear() {
|
||||
await rmRecursive(r("."));
|
||||
},
|
||||
async dispose() {
|
||||
if (_watcher) {
|
||||
await _watcher.close();
|
||||
}
|
||||
},
|
||||
watch(callback) {
|
||||
if (_watcher) {
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve2, reject) => {
|
||||
_watcher = watch(opts.base, {
|
||||
ignoreInitial: true,
|
||||
ignored: opts.ignore,
|
||||
...opts.watchOptions
|
||||
}).on("ready", () => {
|
||||
resolve2(() => _watcher.close().then(() => _watcher = void 0));
|
||||
}).on("error", reject).on("all", (eventName, path) => {
|
||||
path = relative(opts.base, path);
|
||||
if (eventName === "change" || eventName === "add") {
|
||||
callback("update", path);
|
||||
} else if (eventName === "unlink") {
|
||||
callback("remove", path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
131
node_modules/unstorage/dist/drivers/github.cjs
generated
vendored
Normal file
131
node_modules/unstorage/dist/drivers/github.cjs
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _ofetch = require("ofetch");
|
||||
|
||||
var _ufo = require("ufo");
|
||||
|
||||
const defaultOptions = {
|
||||
repo: null,
|
||||
branch: "main",
|
||||
ttl: 600,
|
||||
dir: "",
|
||||
apiURL: "https://api.github.com",
|
||||
cdnURL: "https://raw.githubusercontent.com"
|
||||
};
|
||||
|
||||
var _default = (0, _utils.defineDriver)(_opts => {
|
||||
const opts = { ...defaultOptions,
|
||||
..._opts
|
||||
};
|
||||
const rawUrl = (0, _ufo.joinURL)(opts.cdnURL, opts.repo, opts.branch, opts.dir);
|
||||
let files = {};
|
||||
let lastCheck = 0;
|
||||
let syncPromise;
|
||||
|
||||
if (!opts.repo) {
|
||||
throw new Error('[unstorage] [github] Missing required option "repo"');
|
||||
}
|
||||
|
||||
const syncFiles = async () => {
|
||||
if (lastCheck + opts.ttl * 1e3 > Date.now()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!syncPromise) {
|
||||
syncPromise = fetchFiles(opts);
|
||||
}
|
||||
|
||||
files = await syncPromise;
|
||||
lastCheck = Date.now();
|
||||
syncPromise = void 0;
|
||||
};
|
||||
|
||||
return {
|
||||
async getKeys() {
|
||||
await syncFiles();
|
||||
return Object.keys(files);
|
||||
},
|
||||
|
||||
async hasItem(key) {
|
||||
await syncFiles();
|
||||
return key in files;
|
||||
},
|
||||
|
||||
async getItem(key) {
|
||||
await syncFiles();
|
||||
const item = files[key];
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!item.body) {
|
||||
try {
|
||||
item.body = await (0, _ofetch.$fetch)(key.replace(/:/g, "/"), {
|
||||
baseURL: rawUrl,
|
||||
headers: {
|
||||
Authorization: opts.token ? `token ${opts.token}` : void 0
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(`[unstorage] [github] Failed to fetch "${key}"`, {
|
||||
cause: err
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return item.body;
|
||||
},
|
||||
|
||||
async getMeta(key) {
|
||||
await syncFiles();
|
||||
const item = files[key];
|
||||
return item ? item.meta : null;
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
|
||||
async function fetchFiles(opts) {
|
||||
const prefix = (0, _ufo.withTrailingSlash)(opts.dir).replace(/^\//, "");
|
||||
const files = {};
|
||||
|
||||
try {
|
||||
const trees = await (0, _ofetch.$fetch)(`/repos/${opts.repo}/git/trees/${opts.branch}?recursive=1`, {
|
||||
baseURL: opts.apiURL,
|
||||
headers: {
|
||||
Authorization: opts.token ? `token ${opts.token}` : void 0
|
||||
}
|
||||
});
|
||||
|
||||
for (const node of trees.tree) {
|
||||
if (node.type !== "blob" || !node.path.startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const key = node.path.substring(prefix.length).replace(/\//g, ":");
|
||||
files[key] = {
|
||||
meta: {
|
||||
sha: node.sha,
|
||||
mode: node.mode,
|
||||
size: node.size
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`[unstorage] [github] Failed to fetch git tree`, {
|
||||
cause: err
|
||||
});
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
34
node_modules/unstorage/dist/drivers/github.d.ts
generated
vendored
Normal file
34
node_modules/unstorage/dist/drivers/github.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
export interface GithubOptions {
|
||||
/**
|
||||
* The name of the repository. (e.g. `username/my-repo`)
|
||||
* Required
|
||||
*/
|
||||
repo: string;
|
||||
/**
|
||||
* The branch to fetch. (e.g. `dev`)
|
||||
* @default "main"
|
||||
*/
|
||||
branch: string;
|
||||
/**
|
||||
* @default ""
|
||||
*/
|
||||
dir: string;
|
||||
/**
|
||||
* @default 600
|
||||
*/
|
||||
ttl: number;
|
||||
/**
|
||||
* Github API token (recommended)
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
* @default "https://api.github.com"
|
||||
*/
|
||||
apiURL?: string;
|
||||
/**
|
||||
* @default "https://raw.githubusercontent.com"
|
||||
*/
|
||||
cdnURL?: string;
|
||||
}
|
||||
declare const _default: (opts?: GithubOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
95
node_modules/unstorage/dist/drivers/github.mjs
generated
vendored
Normal file
95
node_modules/unstorage/dist/drivers/github.mjs
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
import { $fetch } from "ofetch";
|
||||
import { withTrailingSlash, joinURL } from "ufo";
|
||||
const defaultOptions = {
|
||||
repo: null,
|
||||
branch: "main",
|
||||
ttl: 600,
|
||||
dir: "",
|
||||
apiURL: "https://api.github.com",
|
||||
cdnURL: "https://raw.githubusercontent.com"
|
||||
};
|
||||
export default defineDriver((_opts) => {
|
||||
const opts = { ...defaultOptions, ..._opts };
|
||||
const rawUrl = joinURL(opts.cdnURL, opts.repo, opts.branch, opts.dir);
|
||||
let files = {};
|
||||
let lastCheck = 0;
|
||||
let syncPromise;
|
||||
if (!opts.repo) {
|
||||
throw new Error('[unstorage] [github] Missing required option "repo"');
|
||||
}
|
||||
const syncFiles = async () => {
|
||||
if (lastCheck + opts.ttl * 1e3 > Date.now()) {
|
||||
return;
|
||||
}
|
||||
if (!syncPromise) {
|
||||
syncPromise = fetchFiles(opts);
|
||||
}
|
||||
files = await syncPromise;
|
||||
lastCheck = Date.now();
|
||||
syncPromise = void 0;
|
||||
};
|
||||
return {
|
||||
async getKeys() {
|
||||
await syncFiles();
|
||||
return Object.keys(files);
|
||||
},
|
||||
async hasItem(key) {
|
||||
await syncFiles();
|
||||
return key in files;
|
||||
},
|
||||
async getItem(key) {
|
||||
await syncFiles();
|
||||
const item = files[key];
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
if (!item.body) {
|
||||
try {
|
||||
item.body = await $fetch(key.replace(/:/g, "/"), {
|
||||
baseURL: rawUrl,
|
||||
headers: {
|
||||
Authorization: opts.token ? `token ${opts.token}` : void 0
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(`[unstorage] [github] Failed to fetch "${key}"`, { cause: err });
|
||||
}
|
||||
}
|
||||
return item.body;
|
||||
},
|
||||
async getMeta(key) {
|
||||
await syncFiles();
|
||||
const item = files[key];
|
||||
return item ? item.meta : null;
|
||||
}
|
||||
};
|
||||
});
|
||||
async function fetchFiles(opts) {
|
||||
const prefix = withTrailingSlash(opts.dir).replace(/^\//, "");
|
||||
const files = {};
|
||||
try {
|
||||
const trees = await $fetch(`/repos/${opts.repo}/git/trees/${opts.branch}?recursive=1`, {
|
||||
baseURL: opts.apiURL,
|
||||
headers: {
|
||||
Authorization: opts.token ? `token ${opts.token}` : void 0
|
||||
}
|
||||
});
|
||||
for (const node of trees.tree) {
|
||||
if (node.type !== "blob" || !node.path.startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
const key = node.path.substring(prefix.length).replace(/\//g, ":");
|
||||
files[key] = {
|
||||
meta: {
|
||||
sha: node.sha,
|
||||
mode: node.mode,
|
||||
size: node.size
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`[unstorage] [github] Failed to fetch git tree`, { cause: err });
|
||||
}
|
||||
return files;
|
||||
}
|
||||
70
node_modules/unstorage/dist/drivers/http.cjs
generated
vendored
Normal file
70
node_modules/unstorage/dist/drivers/http.cjs
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _ofetch = require("ofetch");
|
||||
|
||||
var _ufo = require("ufo");
|
||||
|
||||
var _default = (0, _utils.defineDriver)((opts = {}) => {
|
||||
const r = key => (0, _ufo.joinURL)(opts.base, key.replace(/:/g, "/"));
|
||||
|
||||
return {
|
||||
hasItem(key) {
|
||||
return (0, _ofetch.$fetch)(r(key), {
|
||||
method: "HEAD"
|
||||
}).then(() => true).catch(() => false);
|
||||
},
|
||||
|
||||
async getItem(key) {
|
||||
const value = await (0, _ofetch.$fetch)(r(key));
|
||||
return value;
|
||||
},
|
||||
|
||||
async getMeta(key) {
|
||||
const res = await _ofetch.$fetch.raw(r(key), {
|
||||
method: "HEAD"
|
||||
});
|
||||
let mtime = void 0;
|
||||
|
||||
const _lastModified = res.headers.get("last-modified");
|
||||
|
||||
if (_lastModified) {
|
||||
mtime = new Date(_lastModified);
|
||||
}
|
||||
|
||||
return {
|
||||
status: res.status,
|
||||
mtime
|
||||
};
|
||||
},
|
||||
|
||||
async setItem(key, value) {
|
||||
await (0, _ofetch.$fetch)(r(key), {
|
||||
method: "PUT",
|
||||
body: (0, _utils.stringify)(value)
|
||||
});
|
||||
},
|
||||
|
||||
async removeItem(key) {
|
||||
await (0, _ofetch.$fetch)(r(key), {
|
||||
method: "DELETE"
|
||||
});
|
||||
},
|
||||
|
||||
async getKeys() {
|
||||
const value = await (0, _ofetch.$fetch)(r(""));
|
||||
return Array.isArray(value) ? value : [];
|
||||
},
|
||||
|
||||
clear() {}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
5
node_modules/unstorage/dist/drivers/http.d.ts
generated
vendored
Normal file
5
node_modules/unstorage/dist/drivers/http.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface HTTPOptions {
|
||||
base?: string;
|
||||
}
|
||||
declare const _default: (opts?: HTTPOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
40
node_modules/unstorage/dist/drivers/http.mjs
generated
vendored
Normal file
40
node_modules/unstorage/dist/drivers/http.mjs
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
import { stringify } from "./utils/index.mjs";
|
||||
import { $fetch } from "ofetch";
|
||||
import { joinURL } from "ufo";
|
||||
export default defineDriver((opts = {}) => {
|
||||
const r = (key) => joinURL(opts.base, key.replace(/:/g, "/"));
|
||||
return {
|
||||
hasItem(key) {
|
||||
return $fetch(r(key), { method: "HEAD" }).then(() => true).catch(() => false);
|
||||
},
|
||||
async getItem(key) {
|
||||
const value = await $fetch(r(key));
|
||||
return value;
|
||||
},
|
||||
async getMeta(key) {
|
||||
const res = await $fetch.raw(r(key), { method: "HEAD" });
|
||||
let mtime = void 0;
|
||||
const _lastModified = res.headers.get("last-modified");
|
||||
if (_lastModified) {
|
||||
mtime = new Date(_lastModified);
|
||||
}
|
||||
return {
|
||||
status: res.status,
|
||||
mtime
|
||||
};
|
||||
},
|
||||
async setItem(key, value) {
|
||||
await $fetch(r(key), { method: "PUT", body: stringify(value) });
|
||||
},
|
||||
async removeItem(key) {
|
||||
await $fetch(r(key), { method: "DELETE" });
|
||||
},
|
||||
async getKeys() {
|
||||
const value = await $fetch(r(""));
|
||||
return Array.isArray(value) ? value : [];
|
||||
},
|
||||
clear() {
|
||||
}
|
||||
};
|
||||
});
|
||||
83
node_modules/unstorage/dist/drivers/localstorage.cjs
generated
vendored
Normal file
83
node_modules/unstorage/dist/drivers/localstorage.cjs
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _default = (0, _utils.defineDriver)((opts = {}) => {
|
||||
if (!opts.window) {
|
||||
opts.window = typeof window !== "undefined" ? window : void 0;
|
||||
}
|
||||
|
||||
if (!opts.localStorage) {
|
||||
opts.localStorage = opts.window?.localStorage;
|
||||
}
|
||||
|
||||
if (!opts.localStorage) {
|
||||
throw new Error("localStorage not available");
|
||||
}
|
||||
|
||||
const r = key => (opts.base ? opts.base + ":" : "") + key;
|
||||
|
||||
let _storageListener;
|
||||
|
||||
return {
|
||||
hasItem(key) {
|
||||
return Object.prototype.hasOwnProperty.call(opts.localStorage, r(key));
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
return opts.localStorage.getItem(r(key));
|
||||
},
|
||||
|
||||
setItem(key, value) {
|
||||
return opts.localStorage.setItem(r(key), value);
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
return opts.localStorage.removeItem(r(key));
|
||||
},
|
||||
|
||||
getKeys() {
|
||||
return Object.keys(opts.localStorage);
|
||||
},
|
||||
|
||||
clear() {
|
||||
if (!opts.base) {
|
||||
opts.localStorage.clear();
|
||||
} else {
|
||||
for (const key of Object.keys(opts.localStorage)) {
|
||||
opts.localStorage?.removeItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.window && _storageListener) {
|
||||
opts.window.removeEventListener("storage", _storageListener);
|
||||
}
|
||||
},
|
||||
|
||||
watch(callback) {
|
||||
if (!opts.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
_storageListener = ev => {
|
||||
if (ev.key) {
|
||||
callback(ev.newValue ? "update" : "remove", ev.key);
|
||||
}
|
||||
};
|
||||
|
||||
opts.window.addEventListener("storage", _storageListener);
|
||||
return () => {
|
||||
opts.window.removeEventListener("storage", _storageListener);
|
||||
_storageListener = void 0;
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
7
node_modules/unstorage/dist/drivers/localstorage.d.ts
generated
vendored
Normal file
7
node_modules/unstorage/dist/drivers/localstorage.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface LocalStorageOptions {
|
||||
base?: string;
|
||||
window?: typeof window;
|
||||
localStorage?: typeof window.localStorage;
|
||||
}
|
||||
declare const _default: (opts?: LocalStorageOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
58
node_modules/unstorage/dist/drivers/localstorage.mjs
generated
vendored
Normal file
58
node_modules/unstorage/dist/drivers/localstorage.mjs
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
export default defineDriver((opts = {}) => {
|
||||
if (!opts.window) {
|
||||
opts.window = typeof window !== "undefined" ? window : void 0;
|
||||
}
|
||||
if (!opts.localStorage) {
|
||||
opts.localStorage = opts.window?.localStorage;
|
||||
}
|
||||
if (!opts.localStorage) {
|
||||
throw new Error("localStorage not available");
|
||||
}
|
||||
const r = (key) => (opts.base ? opts.base + ":" : "") + key;
|
||||
let _storageListener;
|
||||
return {
|
||||
hasItem(key) {
|
||||
return Object.prototype.hasOwnProperty.call(opts.localStorage, r(key));
|
||||
},
|
||||
getItem(key) {
|
||||
return opts.localStorage.getItem(r(key));
|
||||
},
|
||||
setItem(key, value) {
|
||||
return opts.localStorage.setItem(r(key), value);
|
||||
},
|
||||
removeItem(key) {
|
||||
return opts.localStorage.removeItem(r(key));
|
||||
},
|
||||
getKeys() {
|
||||
return Object.keys(opts.localStorage);
|
||||
},
|
||||
clear() {
|
||||
if (!opts.base) {
|
||||
opts.localStorage.clear();
|
||||
} else {
|
||||
for (const key of Object.keys(opts.localStorage)) {
|
||||
opts.localStorage?.removeItem(key);
|
||||
}
|
||||
}
|
||||
if (opts.window && _storageListener) {
|
||||
opts.window.removeEventListener("storage", _storageListener);
|
||||
}
|
||||
},
|
||||
watch(callback) {
|
||||
if (!opts.window) {
|
||||
return;
|
||||
}
|
||||
_storageListener = (ev) => {
|
||||
if (ev.key) {
|
||||
callback(ev.newValue ? "update" : "remove", ev.key);
|
||||
}
|
||||
};
|
||||
opts.window.addEventListener("storage", _storageListener);
|
||||
return () => {
|
||||
opts.window.removeEventListener("storage", _storageListener);
|
||||
_storageListener = void 0;
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
44
node_modules/unstorage/dist/drivers/memory.cjs
generated
vendored
Normal file
44
node_modules/unstorage/dist/drivers/memory.cjs
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _default = (0, _utils.defineDriver)(() => {
|
||||
const data = /* @__PURE__ */new Map();
|
||||
return {
|
||||
hasItem(key) {
|
||||
return data.has(key);
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
return data.get(key) || null;
|
||||
},
|
||||
|
||||
setItem(key, value) {
|
||||
data.set(key, value);
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
data.delete(key);
|
||||
},
|
||||
|
||||
getKeys() {
|
||||
return Array.from(data.keys());
|
||||
},
|
||||
|
||||
clear() {
|
||||
data.clear();
|
||||
},
|
||||
|
||||
dispose() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
2
node_modules/unstorage/dist/drivers/memory.d.ts
generated
vendored
Normal file
2
node_modules/unstorage/dist/drivers/memory.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (opts?: any) => import("../types").Driver;
|
||||
export default _default;
|
||||
27
node_modules/unstorage/dist/drivers/memory.mjs
generated
vendored
Normal file
27
node_modules/unstorage/dist/drivers/memory.mjs
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
export default defineDriver(() => {
|
||||
const data = /* @__PURE__ */ new Map();
|
||||
return {
|
||||
hasItem(key) {
|
||||
return data.has(key);
|
||||
},
|
||||
getItem(key) {
|
||||
return data.get(key) || null;
|
||||
},
|
||||
setItem(key, value) {
|
||||
data.set(key, value);
|
||||
},
|
||||
removeItem(key) {
|
||||
data.delete(key);
|
||||
},
|
||||
getKeys() {
|
||||
return Array.from(data.keys());
|
||||
},
|
||||
clear() {
|
||||
data.clear();
|
||||
},
|
||||
dispose() {
|
||||
data.clear();
|
||||
}
|
||||
};
|
||||
});
|
||||
81
node_modules/unstorage/dist/drivers/overlay.cjs
generated
vendored
Normal file
81
node_modules/unstorage/dist/drivers/overlay.cjs
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
const OVERLAY_REMOVED = "__OVERLAY_REMOVED__";
|
||||
|
||||
var _default = (0, _utils.defineDriver)(options => {
|
||||
return {
|
||||
async hasItem(key) {
|
||||
for (const layer of options.layers) {
|
||||
if (await layer.hasItem(key)) {
|
||||
if (layer === options.layers[0]) {
|
||||
if ((await options.layers[0]?.getItem(key)) === OVERLAY_REMOVED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
async getItem(key) {
|
||||
for (const layer of options.layers) {
|
||||
const value = await layer.getItem(key);
|
||||
|
||||
if (value === OVERLAY_REMOVED) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value !== null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
async setItem(key, value) {
|
||||
await options.layers[0]?.setItem(key, value);
|
||||
},
|
||||
|
||||
async removeItem(key) {
|
||||
await options.layers[0]?.setItem(key, OVERLAY_REMOVED);
|
||||
},
|
||||
|
||||
async getKeys(base) {
|
||||
const allKeys = await Promise.all(options.layers.map(async layer => {
|
||||
const keys = await layer.getKeys(base);
|
||||
return keys.map(key => (0, _utils.normalizeKey)(key));
|
||||
}));
|
||||
const uniqueKeys = Array.from(new Set(allKeys.flat()));
|
||||
const existingKeys = await Promise.all(uniqueKeys.map(async key => {
|
||||
if ((await options.layers[0]?.getItem(key)) === OVERLAY_REMOVED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return key;
|
||||
}));
|
||||
return existingKeys.filter(Boolean);
|
||||
},
|
||||
|
||||
async dispose() {
|
||||
await Promise.all(options.layers.map(async layer => {
|
||||
if (layer.dispose) {
|
||||
await layer.dispose();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
6
node_modules/unstorage/dist/drivers/overlay.d.ts
generated
vendored
Normal file
6
node_modules/unstorage/dist/drivers/overlay.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Driver } from '../types';
|
||||
export interface OverlayStorageOptions {
|
||||
layers: Driver[];
|
||||
}
|
||||
declare const _default: (opts?: OverlayStorageOptions) => Driver;
|
||||
export default _default;
|
||||
59
node_modules/unstorage/dist/drivers/overlay.mjs
generated
vendored
Normal file
59
node_modules/unstorage/dist/drivers/overlay.mjs
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
import { normalizeKey } from "./utils/index.mjs";
|
||||
const OVERLAY_REMOVED = "__OVERLAY_REMOVED__";
|
||||
export default defineDriver((options) => {
|
||||
return {
|
||||
async hasItem(key) {
|
||||
for (const layer of options.layers) {
|
||||
if (await layer.hasItem(key)) {
|
||||
if (layer === options.layers[0]) {
|
||||
if (await options.layers[0]?.getItem(key) === OVERLAY_REMOVED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async getItem(key) {
|
||||
for (const layer of options.layers) {
|
||||
const value = await layer.getItem(key);
|
||||
if (value === OVERLAY_REMOVED) {
|
||||
return null;
|
||||
}
|
||||
if (value !== null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
async setItem(key, value) {
|
||||
await options.layers[0]?.setItem(key, value);
|
||||
},
|
||||
async removeItem(key) {
|
||||
await options.layers[0]?.setItem(key, OVERLAY_REMOVED);
|
||||
},
|
||||
async getKeys(base) {
|
||||
const allKeys = await Promise.all(options.layers.map(async (layer) => {
|
||||
const keys = await layer.getKeys(base);
|
||||
return keys.map((key) => normalizeKey(key));
|
||||
}));
|
||||
const uniqueKeys = Array.from(new Set(allKeys.flat()));
|
||||
const existingKeys = await Promise.all(uniqueKeys.map(async (key) => {
|
||||
if (await options.layers[0]?.getItem(key) === OVERLAY_REMOVED) {
|
||||
return false;
|
||||
}
|
||||
return key;
|
||||
}));
|
||||
return existingKeys.filter(Boolean);
|
||||
},
|
||||
async dispose() {
|
||||
await Promise.all(options.layers.map(async (layer) => {
|
||||
if (layer.dispose) {
|
||||
await layer.dispose();
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
});
|
||||
61
node_modules/unstorage/dist/drivers/redis.cjs
generated
vendored
Normal file
61
node_modules/unstorage/dist/drivers/redis.cjs
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
module.exports = void 0;
|
||||
|
||||
var _utils = require("./utils/index.cjs");
|
||||
|
||||
var _ioredis = _interopRequireDefault(require("ioredis"));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var _default = (0, _utils.defineDriver)(_opts => {
|
||||
const opts = {
|
||||
lazyConnect: true,
|
||||
..._opts
|
||||
};
|
||||
const redis = opts.url ? new _ioredis.default(opts?.url, opts) : new _ioredis.default(opts);
|
||||
let base = opts?.base || "";
|
||||
|
||||
if (base && !base.endsWith(":")) {
|
||||
base += ":";
|
||||
}
|
||||
|
||||
const r = key => base + key;
|
||||
|
||||
return {
|
||||
hasItem(key) {
|
||||
return redis.exists(r(key)).then(Boolean);
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
return redis.get(r(key));
|
||||
},
|
||||
|
||||
setItem(key, value) {
|
||||
return redis.set(r(key), value).then(() => {});
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
return redis.del(r(key)).then(() => {});
|
||||
},
|
||||
|
||||
getKeys() {
|
||||
return redis.keys(r("*"));
|
||||
},
|
||||
|
||||
async clear() {
|
||||
const keys = await redis.keys(r("*"));
|
||||
return redis.del(keys.map(key => r(key))).then(() => {});
|
||||
},
|
||||
|
||||
dispose() {
|
||||
return redis.disconnect();
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = _default;
|
||||
7
node_modules/unstorage/dist/drivers/redis.d.ts
generated
vendored
Normal file
7
node_modules/unstorage/dist/drivers/redis.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { RedisOptions as _RedisOptions } from 'ioredis';
|
||||
export interface RedisOptions extends _RedisOptions {
|
||||
base: string;
|
||||
url: string;
|
||||
}
|
||||
declare const _default: (opts?: RedisOptions) => import("../types").Driver;
|
||||
export default _default;
|
||||
38
node_modules/unstorage/dist/drivers/redis.mjs
generated
vendored
Normal file
38
node_modules/unstorage/dist/drivers/redis.mjs
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { defineDriver } from "./utils/index.mjs";
|
||||
import Redis from "ioredis";
|
||||
export default defineDriver((_opts) => {
|
||||
const opts = { lazyConnect: true, ..._opts };
|
||||
const redis = opts.url ? new Redis(opts?.url, opts) : new Redis(opts);
|
||||
let base = opts?.base || "";
|
||||
if (base && !base.endsWith(":")) {
|
||||
base += ":";
|
||||
}
|
||||
const r = (key) => base + key;
|
||||
return {
|
||||
hasItem(key) {
|
||||
return redis.exists(r(key)).then(Boolean);
|
||||
},
|
||||
getItem(key) {
|
||||
return redis.get(r(key));
|
||||
},
|
||||
setItem(key, value) {
|
||||
return redis.set(r(key), value).then(() => {
|
||||
});
|
||||
},
|
||||
removeItem(key) {
|
||||
return redis.del(r(key)).then(() => {
|
||||
});
|
||||
},
|
||||
getKeys() {
|
||||
return redis.keys(r("*"));
|
||||
},
|
||||
async clear() {
|
||||
const keys = await redis.keys(r("*"));
|
||||
return redis.del(keys.map((key) => r(key))).then(() => {
|
||||
});
|
||||
},
|
||||
dispose() {
|
||||
return redis.disconnect();
|
||||
}
|
||||
};
|
||||
});
|
||||
30
node_modules/unstorage/dist/drivers/utils/index.cjs
generated
vendored
Normal file
30
node_modules/unstorage/dist/drivers/utils/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.defineDriver = defineDriver;
|
||||
exports.isPrimitive = isPrimitive;
|
||||
exports.normalizeKey = normalizeKey;
|
||||
exports.stringify = stringify;
|
||||
|
||||
function defineDriver(factory) {
|
||||
return factory;
|
||||
}
|
||||
|
||||
function isPrimitive(arg) {
|
||||
const type = typeof arg;
|
||||
return arg === null || type !== "object" && type !== "function";
|
||||
}
|
||||
|
||||
function stringify(arg) {
|
||||
return isPrimitive(arg) ? arg + "" : JSON.stringify(arg);
|
||||
}
|
||||
|
||||
function normalizeKey(key) {
|
||||
if (!key) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return key.replace(/[/\\]/g, ":").replace(/^:|:$/g, "");
|
||||
}
|
||||
7
node_modules/unstorage/dist/drivers/utils/index.d.ts
generated
vendored
Normal file
7
node_modules/unstorage/dist/drivers/utils/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { Driver } from '../../types';
|
||||
declare type DriverFactory<T> = (opts?: T) => Driver;
|
||||
export declare function defineDriver<T = any>(factory: DriverFactory<T>): DriverFactory<T>;
|
||||
export declare function isPrimitive(arg: any): boolean;
|
||||
export declare function stringify(arg: any): string;
|
||||
export declare function normalizeKey(key: string | undefined): string;
|
||||
export {};
|
||||
16
node_modules/unstorage/dist/drivers/utils/index.mjs
generated
vendored
Normal file
16
node_modules/unstorage/dist/drivers/utils/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export function defineDriver(factory) {
|
||||
return factory;
|
||||
}
|
||||
export function isPrimitive(arg) {
|
||||
const type = typeof arg;
|
||||
return arg === null || type !== "object" && type !== "function";
|
||||
}
|
||||
export function stringify(arg) {
|
||||
return isPrimitive(arg) ? arg + "" : JSON.stringify(arg);
|
||||
}
|
||||
export function normalizeKey(key) {
|
||||
if (!key) {
|
||||
return "";
|
||||
}
|
||||
return key.replace(/[/\\]/g, ":").replace(/^:|:$/g, "");
|
||||
}
|
||||
92
node_modules/unstorage/dist/drivers/utils/node-fs.cjs
generated
vendored
Normal file
92
node_modules/unstorage/dist/drivers/utils/node-fs.cjs
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ensuredir = ensuredir;
|
||||
exports.readFile = readFile;
|
||||
exports.readdir = readdir;
|
||||
exports.readdirRecursive = readdirRecursive;
|
||||
exports.rmRecursive = rmRecursive;
|
||||
exports.stat = stat;
|
||||
exports.unlink = unlink;
|
||||
exports.writeFile = writeFile;
|
||||
|
||||
var _fs = require("fs");
|
||||
|
||||
var _path = require("path");
|
||||
|
||||
function ignoreNotfound(err) {
|
||||
return err.code === "ENOENT" || err.code === "EISDIR" ? null : err;
|
||||
}
|
||||
|
||||
function ignoreExists(err) {
|
||||
return err.code === "EEXIST" ? null : err;
|
||||
}
|
||||
|
||||
async function writeFile(path, data) {
|
||||
await ensuredir((0, _path.dirname)(path));
|
||||
return _fs.promises.writeFile(path, data, "utf8");
|
||||
}
|
||||
|
||||
function readFile(path) {
|
||||
return _fs.promises.readFile(path, "utf8").catch(ignoreNotfound);
|
||||
}
|
||||
|
||||
function stat(path) {
|
||||
return _fs.promises.stat(path).catch(ignoreNotfound);
|
||||
}
|
||||
|
||||
function unlink(path) {
|
||||
return _fs.promises.unlink(path).catch(ignoreNotfound);
|
||||
}
|
||||
|
||||
function readdir(dir) {
|
||||
return _fs.promises.readdir(dir, {
|
||||
withFileTypes: true
|
||||
}).catch(ignoreNotfound).then(r => r || []);
|
||||
}
|
||||
|
||||
async function ensuredir(dir) {
|
||||
if ((0, _fs.existsSync)(dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await ensuredir((0, _path.dirname)(dir)).catch(ignoreExists);
|
||||
await _fs.promises.mkdir(dir).catch(ignoreExists);
|
||||
}
|
||||
|
||||
async function readdirRecursive(dir, ignore) {
|
||||
if (ignore && ignore(dir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const entries = await readdir(dir);
|
||||
const files = [];
|
||||
await Promise.all(entries.map(async entry => {
|
||||
const entryPath = (0, _path.resolve)(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
const dirFiles = await readdirRecursive(entryPath, ignore);
|
||||
files.push(...dirFiles.map(f => entry.name + "/" + f));
|
||||
} else {
|
||||
if (ignore && !ignore(entry.name)) {
|
||||
files.push(entry.name);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return files;
|
||||
}
|
||||
|
||||
async function rmRecursive(dir) {
|
||||
const entries = await readdir(dir);
|
||||
await Promise.all(entries.map(entry => {
|
||||
const entryPath = (0, _path.resolve)(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
return rmRecursive(entryPath).then(() => _fs.promises.rmdir(entryPath));
|
||||
} else {
|
||||
return _fs.promises.unlink(entryPath);
|
||||
}
|
||||
}));
|
||||
}
|
||||
10
node_modules/unstorage/dist/drivers/utils/node-fs.d.ts
generated
vendored
Normal file
10
node_modules/unstorage/dist/drivers/utils/node-fs.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/// <reference types="node" />
|
||||
import { Dirent } from 'fs';
|
||||
export declare function writeFile(path: string, data: string): Promise<void>;
|
||||
export declare function readFile(path: string): Promise<any>;
|
||||
export declare function stat(path: string): Promise<any>;
|
||||
export declare function unlink(path: string): Promise<any>;
|
||||
export declare function readdir(dir: string): Promise<Dirent[]>;
|
||||
export declare function ensuredir(dir: string): Promise<void>;
|
||||
export declare function readdirRecursive(dir: string, ignore?: (p: string) => boolean): Promise<string[]>;
|
||||
export declare function rmRecursive(dir: string): Promise<void>;
|
||||
61
node_modules/unstorage/dist/drivers/utils/node-fs.mjs
generated
vendored
Normal file
61
node_modules/unstorage/dist/drivers/utils/node-fs.mjs
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import { existsSync, promises as fsPromises } from "fs";
|
||||
import { resolve, dirname } from "path";
|
||||
function ignoreNotfound(err) {
|
||||
return err.code === "ENOENT" || err.code === "EISDIR" ? null : err;
|
||||
}
|
||||
function ignoreExists(err) {
|
||||
return err.code === "EEXIST" ? null : err;
|
||||
}
|
||||
export async function writeFile(path, data) {
|
||||
await ensuredir(dirname(path));
|
||||
return fsPromises.writeFile(path, data, "utf8");
|
||||
}
|
||||
export function readFile(path) {
|
||||
return fsPromises.readFile(path, "utf8").catch(ignoreNotfound);
|
||||
}
|
||||
export function stat(path) {
|
||||
return fsPromises.stat(path).catch(ignoreNotfound);
|
||||
}
|
||||
export function unlink(path) {
|
||||
return fsPromises.unlink(path).catch(ignoreNotfound);
|
||||
}
|
||||
export function readdir(dir) {
|
||||
return fsPromises.readdir(dir, { withFileTypes: true }).catch(ignoreNotfound).then((r) => r || []);
|
||||
}
|
||||
export async function ensuredir(dir) {
|
||||
if (existsSync(dir)) {
|
||||
return;
|
||||
}
|
||||
await ensuredir(dirname(dir)).catch(ignoreExists);
|
||||
await fsPromises.mkdir(dir).catch(ignoreExists);
|
||||
}
|
||||
export async function readdirRecursive(dir, ignore) {
|
||||
if (ignore && ignore(dir)) {
|
||||
return [];
|
||||
}
|
||||
const entries = await readdir(dir);
|
||||
const files = [];
|
||||
await Promise.all(entries.map(async (entry) => {
|
||||
const entryPath = resolve(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
const dirFiles = await readdirRecursive(entryPath, ignore);
|
||||
files.push(...dirFiles.map((f) => entry.name + "/" + f));
|
||||
} else {
|
||||
if (ignore && !ignore(entry.name)) {
|
||||
files.push(entry.name);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return files;
|
||||
}
|
||||
export async function rmRecursive(dir) {
|
||||
const entries = await readdir(dir);
|
||||
await Promise.all(entries.map((entry) => {
|
||||
const entryPath = resolve(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
return rmRecursive(entryPath).then(() => fsPromises.rmdir(entryPath));
|
||||
} else {
|
||||
return fsPromises.unlink(entryPath);
|
||||
}
|
||||
}));
|
||||
}
|
||||
325
node_modules/unstorage/dist/index.cjs
generated
vendored
Normal file
325
node_modules/unstorage/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
'use strict';
|
||||
|
||||
const destr = require('destr');
|
||||
const _utils = require('./shared/unstorage.e5f2cd8b.cjs');
|
||||
|
||||
function defineDriver(factory) {
|
||||
return factory;
|
||||
}
|
||||
|
||||
const memory = defineDriver(() => {
|
||||
const data = /* @__PURE__ */ new Map();
|
||||
return {
|
||||
hasItem(key) {
|
||||
return data.has(key);
|
||||
},
|
||||
getItem(key) {
|
||||
return data.get(key) || null;
|
||||
},
|
||||
setItem(key, value) {
|
||||
data.set(key, value);
|
||||
},
|
||||
removeItem(key) {
|
||||
data.delete(key);
|
||||
},
|
||||
getKeys() {
|
||||
return Array.from(data.keys());
|
||||
},
|
||||
clear() {
|
||||
data.clear();
|
||||
},
|
||||
dispose() {
|
||||
data.clear();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const storageKeyProperties = [
|
||||
"hasItem",
|
||||
"getItem",
|
||||
"setItem",
|
||||
"removeItem",
|
||||
"getMeta",
|
||||
"setMeta",
|
||||
"removeMeta",
|
||||
"getKeys",
|
||||
"clear",
|
||||
"mount",
|
||||
"unmount"
|
||||
];
|
||||
function prefixStorage(storage, base) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (!base) {
|
||||
return storage;
|
||||
}
|
||||
const nsStorage = { ...storage };
|
||||
for (const property of storageKeyProperties) {
|
||||
nsStorage[property] = (key = "", ...arguments_) => storage[property](base + key, ...arguments_);
|
||||
}
|
||||
nsStorage.getKeys = (key = "", ...arguments_) => storage.getKeys(base + key, ...arguments_).then((keys) => keys.map((key2) => key2.slice(base.length)));
|
||||
return nsStorage;
|
||||
}
|
||||
function normalizeKey(key) {
|
||||
if (!key) {
|
||||
return "";
|
||||
}
|
||||
return key.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "");
|
||||
}
|
||||
function joinKeys(...keys) {
|
||||
return normalizeKey(keys.join(":"));
|
||||
}
|
||||
function normalizeBaseKey(base) {
|
||||
base = normalizeKey(base);
|
||||
return base ? base + ":" : "";
|
||||
}
|
||||
|
||||
function createStorage(options = {}) {
|
||||
const context = {
|
||||
mounts: { "": options.driver || memory() },
|
||||
mountpoints: [""],
|
||||
watching: false,
|
||||
watchListeners: [],
|
||||
unwatch: {}
|
||||
};
|
||||
const getMount = (key) => {
|
||||
for (const base of context.mountpoints) {
|
||||
if (key.startsWith(base)) {
|
||||
return {
|
||||
relativeKey: key.slice(base.length),
|
||||
driver: context.mounts[base]
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
relativeKey: key,
|
||||
driver: context.mounts[""]
|
||||
};
|
||||
};
|
||||
const getMounts = (base, includeParent) => {
|
||||
return context.mountpoints.filter((mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)).map((mountpoint) => ({
|
||||
relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0,
|
||||
mountpoint,
|
||||
driver: context.mounts[mountpoint]
|
||||
}));
|
||||
};
|
||||
const onChange = (event, key) => {
|
||||
if (!context.watching) {
|
||||
return;
|
||||
}
|
||||
key = normalizeKey(key);
|
||||
for (const listener of context.watchListeners) {
|
||||
listener(event, key);
|
||||
}
|
||||
};
|
||||
const startWatch = async () => {
|
||||
if (context.watching) {
|
||||
return;
|
||||
}
|
||||
context.watching = true;
|
||||
for (const mountpoint in context.mounts) {
|
||||
context.unwatch[mountpoint] = await watch(context.mounts[mountpoint], onChange, mountpoint);
|
||||
}
|
||||
};
|
||||
const stopWatch = async () => {
|
||||
if (!context.watching) {
|
||||
return;
|
||||
}
|
||||
for (const mountpoint in context.unwatch) {
|
||||
await context.unwatch[mountpoint]();
|
||||
}
|
||||
context.unwatch = {};
|
||||
context.watching = false;
|
||||
};
|
||||
const storage = {
|
||||
hasItem(key) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
return _utils.asyncCall(driver.hasItem, relativeKey);
|
||||
},
|
||||
getItem(key) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
return _utils.asyncCall(driver.getItem, relativeKey).then((value) => destr(value));
|
||||
},
|
||||
async setItem(key, value) {
|
||||
if (value === void 0) {
|
||||
return storage.removeItem(key);
|
||||
}
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
if (!driver.setItem) {
|
||||
return;
|
||||
}
|
||||
await _utils.asyncCall(driver.setItem, relativeKey, _utils.stringify(value));
|
||||
if (!driver.watch) {
|
||||
onChange("update", key);
|
||||
}
|
||||
},
|
||||
async removeItem(key, removeMeta = true) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
if (!driver.removeItem) {
|
||||
return;
|
||||
}
|
||||
await _utils.asyncCall(driver.removeItem, relativeKey);
|
||||
if (removeMeta) {
|
||||
await _utils.asyncCall(driver.removeItem, relativeKey + "$");
|
||||
}
|
||||
if (!driver.watch) {
|
||||
onChange("remove", key);
|
||||
}
|
||||
},
|
||||
async getMeta(key, nativeMetaOnly) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
const meta = /* @__PURE__ */ Object.create(null);
|
||||
if (driver.getMeta) {
|
||||
Object.assign(meta, await _utils.asyncCall(driver.getMeta, relativeKey));
|
||||
}
|
||||
if (!nativeMetaOnly) {
|
||||
const value = await _utils.asyncCall(driver.getItem, relativeKey + "$").then((value_) => destr(value_));
|
||||
if (value && typeof value === "object") {
|
||||
if (typeof value.atime === "string") {
|
||||
value.atime = new Date(value.atime);
|
||||
}
|
||||
if (typeof value.mtime === "string") {
|
||||
value.mtime = new Date(value.mtime);
|
||||
}
|
||||
Object.assign(meta, value);
|
||||
}
|
||||
}
|
||||
return meta;
|
||||
},
|
||||
setMeta(key, value) {
|
||||
return this.setItem(key + "$", value);
|
||||
},
|
||||
removeMeta(key) {
|
||||
return this.removeItem(key + "$");
|
||||
},
|
||||
async getKeys(base) {
|
||||
base = normalizeBaseKey(base);
|
||||
const mounts = getMounts(base, true);
|
||||
let maskedMounts = [];
|
||||
const allKeys = [];
|
||||
for (const mount of mounts) {
|
||||
const rawKeys = await _utils.asyncCall(mount.driver.getKeys, mount.relativeBase);
|
||||
const keys = rawKeys.map((key) => mount.mountpoint + normalizeKey(key)).filter((key) => !maskedMounts.some((p) => key.startsWith(p)));
|
||||
allKeys.push(...keys);
|
||||
maskedMounts = [
|
||||
mount.mountpoint,
|
||||
...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))
|
||||
];
|
||||
}
|
||||
return base ? allKeys.filter((key) => key.startsWith(base) && !key.endsWith("$")) : allKeys.filter((key) => !key.endsWith("$"));
|
||||
},
|
||||
async clear(base) {
|
||||
base = normalizeBaseKey(base);
|
||||
await Promise.all(getMounts(base, false).map(async (m) => {
|
||||
if (m.driver.clear) {
|
||||
return _utils.asyncCall(m.driver.clear);
|
||||
}
|
||||
if (m.driver.removeItem) {
|
||||
const keys = await m.driver.getKeys();
|
||||
return Promise.all(keys.map((key) => m.driver.removeItem(key)));
|
||||
}
|
||||
}));
|
||||
},
|
||||
async dispose() {
|
||||
await Promise.all(Object.values(context.mounts).map((driver) => dispose(driver)));
|
||||
},
|
||||
async watch(callback) {
|
||||
await startWatch();
|
||||
context.watchListeners.push(callback);
|
||||
return async () => {
|
||||
context.watchListeners = context.watchListeners.filter((listener) => listener !== callback);
|
||||
if (context.watchListeners.length === 0) {
|
||||
await stopWatch();
|
||||
}
|
||||
};
|
||||
},
|
||||
async unwatch() {
|
||||
context.watchListeners = [];
|
||||
await stopWatch();
|
||||
},
|
||||
mount(base, driver) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (base && context.mounts[base]) {
|
||||
throw new Error(`already mounted at ${base}`);
|
||||
}
|
||||
if (base) {
|
||||
context.mountpoints.push(base);
|
||||
context.mountpoints.sort((a, b) => b.length - a.length);
|
||||
}
|
||||
context.mounts[base] = driver;
|
||||
if (context.watching) {
|
||||
Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => {
|
||||
context.unwatch[base] = unwatcher;
|
||||
}).catch(console.error);
|
||||
}
|
||||
return storage;
|
||||
},
|
||||
async unmount(base, _dispose = true) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (!base || !context.mounts[base]) {
|
||||
return;
|
||||
}
|
||||
if (context.watching && base in context.unwatch) {
|
||||
context.unwatch[base]();
|
||||
delete context.unwatch[base];
|
||||
}
|
||||
if (_dispose) {
|
||||
await dispose(context.mounts[base]);
|
||||
}
|
||||
context.mountpoints = context.mountpoints.filter((key) => key !== base);
|
||||
delete context.mounts[base];
|
||||
}
|
||||
};
|
||||
return storage;
|
||||
}
|
||||
async function snapshot(storage, base) {
|
||||
base = normalizeBaseKey(base);
|
||||
const keys = await storage.getKeys(base);
|
||||
const snapshot2 = {};
|
||||
await Promise.all(keys.map(async (key) => {
|
||||
snapshot2[key.slice(base.length)] = await storage.getItem(key);
|
||||
}));
|
||||
return snapshot2;
|
||||
}
|
||||
async function restoreSnapshot(driver, snapshot2, base = "") {
|
||||
base = normalizeBaseKey(base);
|
||||
await Promise.all(Object.entries(snapshot2).map((e) => driver.setItem(base + e[0], e[1])));
|
||||
}
|
||||
function watch(driver, onChange, base) {
|
||||
return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {
|
||||
};
|
||||
}
|
||||
async function dispose(driver) {
|
||||
if (typeof driver.dispose === "function") {
|
||||
await _utils.asyncCall(driver.dispose);
|
||||
}
|
||||
}
|
||||
|
||||
const builtinDrivers = {
|
||||
cloudflareKVHTTP: "unstorage/drivers/cloudflare-kv-http",
|
||||
cloudflareKVBinding: "unstorage/drivers/cloudflare-kv-binding",
|
||||
"cloudflare-kv-http": "unstorage/drivers/cloudflare-kv-http",
|
||||
"cloudflare-kv-binding": "unstorage/drivers/cloudflare-kv-binding",
|
||||
fs: "unstorage/drivers/fs",
|
||||
github: "unstorage/drivers/github",
|
||||
http: "unstorage/drivers/http",
|
||||
localStorage: "unstorage/drivers/localstorage",
|
||||
localstorage: "unstorage/drivers/localstorage",
|
||||
memory: "unstorage/drivers/memory",
|
||||
overlay: "unstorage/drivers/overlay",
|
||||
redis: "unstorage/drivers/redis"
|
||||
};
|
||||
|
||||
exports.builtinDrivers = builtinDrivers;
|
||||
exports.createStorage = createStorage;
|
||||
exports.defineDriver = defineDriver;
|
||||
exports.joinKeys = joinKeys;
|
||||
exports.normalizeBaseKey = normalizeBaseKey;
|
||||
exports.normalizeKey = normalizeKey;
|
||||
exports.prefixStorage = prefixStorage;
|
||||
exports.restoreSnapshot = restoreSnapshot;
|
||||
exports.snapshot = snapshot;
|
||||
36
node_modules/unstorage/dist/index.d.ts
generated
vendored
Normal file
36
node_modules/unstorage/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { D as Driver, S as Storage, a as StorageValue } from './types-227df1cc.js';
|
||||
export { D as Driver, S as Storage, c as StorageMeta, a as StorageValue, U as Unwatch, b as WatchCallback, W as WatchEvent } from './types-227df1cc.js';
|
||||
|
||||
interface CreateStorageOptions {
|
||||
driver?: Driver;
|
||||
}
|
||||
declare function createStorage(options?: CreateStorageOptions): Storage;
|
||||
declare type Snapshot<T = string> = Record<string, T>;
|
||||
declare function snapshot(storage: Storage, base: string): Promise<Snapshot<string>>;
|
||||
declare function restoreSnapshot(driver: Storage, snapshot: Snapshot<StorageValue>, base?: string): Promise<void>;
|
||||
|
||||
declare function prefixStorage(storage: Storage, base: string): Storage;
|
||||
declare function normalizeKey(key?: string): string;
|
||||
declare function joinKeys(...keys: string[]): string;
|
||||
declare function normalizeBaseKey(base?: string): string;
|
||||
|
||||
declare type DriverFactory<T> = (opts?: T) => Driver;
|
||||
declare function defineDriver<T = any>(factory: DriverFactory<T>): DriverFactory<T>;
|
||||
|
||||
declare const builtinDrivers: {
|
||||
cloudflareKVHTTP: string;
|
||||
cloudflareKVBinding: string;
|
||||
"cloudflare-kv-http": string;
|
||||
"cloudflare-kv-binding": string;
|
||||
fs: string;
|
||||
github: string;
|
||||
http: string;
|
||||
localStorage: string;
|
||||
localstorage: string;
|
||||
memory: string;
|
||||
overlay: string;
|
||||
redis: string;
|
||||
};
|
||||
declare type BuiltinDriverName = keyof typeof builtinDrivers;
|
||||
|
||||
export { BuiltinDriverName, CreateStorageOptions, Snapshot, builtinDrivers, createStorage, defineDriver, joinKeys, normalizeBaseKey, normalizeKey, prefixStorage, restoreSnapshot, snapshot };
|
||||
315
node_modules/unstorage/dist/index.mjs
generated
vendored
Normal file
315
node_modules/unstorage/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
import destr from 'destr';
|
||||
import { a as asyncCall, s as stringify } from './shared/unstorage.10149939.mjs';
|
||||
|
||||
function defineDriver(factory) {
|
||||
return factory;
|
||||
}
|
||||
|
||||
const memory = defineDriver(() => {
|
||||
const data = /* @__PURE__ */ new Map();
|
||||
return {
|
||||
hasItem(key) {
|
||||
return data.has(key);
|
||||
},
|
||||
getItem(key) {
|
||||
return data.get(key) || null;
|
||||
},
|
||||
setItem(key, value) {
|
||||
data.set(key, value);
|
||||
},
|
||||
removeItem(key) {
|
||||
data.delete(key);
|
||||
},
|
||||
getKeys() {
|
||||
return Array.from(data.keys());
|
||||
},
|
||||
clear() {
|
||||
data.clear();
|
||||
},
|
||||
dispose() {
|
||||
data.clear();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const storageKeyProperties = [
|
||||
"hasItem",
|
||||
"getItem",
|
||||
"setItem",
|
||||
"removeItem",
|
||||
"getMeta",
|
||||
"setMeta",
|
||||
"removeMeta",
|
||||
"getKeys",
|
||||
"clear",
|
||||
"mount",
|
||||
"unmount"
|
||||
];
|
||||
function prefixStorage(storage, base) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (!base) {
|
||||
return storage;
|
||||
}
|
||||
const nsStorage = { ...storage };
|
||||
for (const property of storageKeyProperties) {
|
||||
nsStorage[property] = (key = "", ...arguments_) => storage[property](base + key, ...arguments_);
|
||||
}
|
||||
nsStorage.getKeys = (key = "", ...arguments_) => storage.getKeys(base + key, ...arguments_).then((keys) => keys.map((key2) => key2.slice(base.length)));
|
||||
return nsStorage;
|
||||
}
|
||||
function normalizeKey(key) {
|
||||
if (!key) {
|
||||
return "";
|
||||
}
|
||||
return key.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "");
|
||||
}
|
||||
function joinKeys(...keys) {
|
||||
return normalizeKey(keys.join(":"));
|
||||
}
|
||||
function normalizeBaseKey(base) {
|
||||
base = normalizeKey(base);
|
||||
return base ? base + ":" : "";
|
||||
}
|
||||
|
||||
function createStorage(options = {}) {
|
||||
const context = {
|
||||
mounts: { "": options.driver || memory() },
|
||||
mountpoints: [""],
|
||||
watching: false,
|
||||
watchListeners: [],
|
||||
unwatch: {}
|
||||
};
|
||||
const getMount = (key) => {
|
||||
for (const base of context.mountpoints) {
|
||||
if (key.startsWith(base)) {
|
||||
return {
|
||||
relativeKey: key.slice(base.length),
|
||||
driver: context.mounts[base]
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
relativeKey: key,
|
||||
driver: context.mounts[""]
|
||||
};
|
||||
};
|
||||
const getMounts = (base, includeParent) => {
|
||||
return context.mountpoints.filter((mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)).map((mountpoint) => ({
|
||||
relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0,
|
||||
mountpoint,
|
||||
driver: context.mounts[mountpoint]
|
||||
}));
|
||||
};
|
||||
const onChange = (event, key) => {
|
||||
if (!context.watching) {
|
||||
return;
|
||||
}
|
||||
key = normalizeKey(key);
|
||||
for (const listener of context.watchListeners) {
|
||||
listener(event, key);
|
||||
}
|
||||
};
|
||||
const startWatch = async () => {
|
||||
if (context.watching) {
|
||||
return;
|
||||
}
|
||||
context.watching = true;
|
||||
for (const mountpoint in context.mounts) {
|
||||
context.unwatch[mountpoint] = await watch(context.mounts[mountpoint], onChange, mountpoint);
|
||||
}
|
||||
};
|
||||
const stopWatch = async () => {
|
||||
if (!context.watching) {
|
||||
return;
|
||||
}
|
||||
for (const mountpoint in context.unwatch) {
|
||||
await context.unwatch[mountpoint]();
|
||||
}
|
||||
context.unwatch = {};
|
||||
context.watching = false;
|
||||
};
|
||||
const storage = {
|
||||
hasItem(key) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
return asyncCall(driver.hasItem, relativeKey);
|
||||
},
|
||||
getItem(key) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
return asyncCall(driver.getItem, relativeKey).then((value) => destr(value));
|
||||
},
|
||||
async setItem(key, value) {
|
||||
if (value === void 0) {
|
||||
return storage.removeItem(key);
|
||||
}
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
if (!driver.setItem) {
|
||||
return;
|
||||
}
|
||||
await asyncCall(driver.setItem, relativeKey, stringify(value));
|
||||
if (!driver.watch) {
|
||||
onChange("update", key);
|
||||
}
|
||||
},
|
||||
async removeItem(key, removeMeta = true) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
if (!driver.removeItem) {
|
||||
return;
|
||||
}
|
||||
await asyncCall(driver.removeItem, relativeKey);
|
||||
if (removeMeta) {
|
||||
await asyncCall(driver.removeItem, relativeKey + "$");
|
||||
}
|
||||
if (!driver.watch) {
|
||||
onChange("remove", key);
|
||||
}
|
||||
},
|
||||
async getMeta(key, nativeMetaOnly) {
|
||||
key = normalizeKey(key);
|
||||
const { relativeKey, driver } = getMount(key);
|
||||
const meta = /* @__PURE__ */ Object.create(null);
|
||||
if (driver.getMeta) {
|
||||
Object.assign(meta, await asyncCall(driver.getMeta, relativeKey));
|
||||
}
|
||||
if (!nativeMetaOnly) {
|
||||
const value = await asyncCall(driver.getItem, relativeKey + "$").then((value_) => destr(value_));
|
||||
if (value && typeof value === "object") {
|
||||
if (typeof value.atime === "string") {
|
||||
value.atime = new Date(value.atime);
|
||||
}
|
||||
if (typeof value.mtime === "string") {
|
||||
value.mtime = new Date(value.mtime);
|
||||
}
|
||||
Object.assign(meta, value);
|
||||
}
|
||||
}
|
||||
return meta;
|
||||
},
|
||||
setMeta(key, value) {
|
||||
return this.setItem(key + "$", value);
|
||||
},
|
||||
removeMeta(key) {
|
||||
return this.removeItem(key + "$");
|
||||
},
|
||||
async getKeys(base) {
|
||||
base = normalizeBaseKey(base);
|
||||
const mounts = getMounts(base, true);
|
||||
let maskedMounts = [];
|
||||
const allKeys = [];
|
||||
for (const mount of mounts) {
|
||||
const rawKeys = await asyncCall(mount.driver.getKeys, mount.relativeBase);
|
||||
const keys = rawKeys.map((key) => mount.mountpoint + normalizeKey(key)).filter((key) => !maskedMounts.some((p) => key.startsWith(p)));
|
||||
allKeys.push(...keys);
|
||||
maskedMounts = [
|
||||
mount.mountpoint,
|
||||
...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))
|
||||
];
|
||||
}
|
||||
return base ? allKeys.filter((key) => key.startsWith(base) && !key.endsWith("$")) : allKeys.filter((key) => !key.endsWith("$"));
|
||||
},
|
||||
async clear(base) {
|
||||
base = normalizeBaseKey(base);
|
||||
await Promise.all(getMounts(base, false).map(async (m) => {
|
||||
if (m.driver.clear) {
|
||||
return asyncCall(m.driver.clear);
|
||||
}
|
||||
if (m.driver.removeItem) {
|
||||
const keys = await m.driver.getKeys();
|
||||
return Promise.all(keys.map((key) => m.driver.removeItem(key)));
|
||||
}
|
||||
}));
|
||||
},
|
||||
async dispose() {
|
||||
await Promise.all(Object.values(context.mounts).map((driver) => dispose(driver)));
|
||||
},
|
||||
async watch(callback) {
|
||||
await startWatch();
|
||||
context.watchListeners.push(callback);
|
||||
return async () => {
|
||||
context.watchListeners = context.watchListeners.filter((listener) => listener !== callback);
|
||||
if (context.watchListeners.length === 0) {
|
||||
await stopWatch();
|
||||
}
|
||||
};
|
||||
},
|
||||
async unwatch() {
|
||||
context.watchListeners = [];
|
||||
await stopWatch();
|
||||
},
|
||||
mount(base, driver) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (base && context.mounts[base]) {
|
||||
throw new Error(`already mounted at ${base}`);
|
||||
}
|
||||
if (base) {
|
||||
context.mountpoints.push(base);
|
||||
context.mountpoints.sort((a, b) => b.length - a.length);
|
||||
}
|
||||
context.mounts[base] = driver;
|
||||
if (context.watching) {
|
||||
Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => {
|
||||
context.unwatch[base] = unwatcher;
|
||||
}).catch(console.error);
|
||||
}
|
||||
return storage;
|
||||
},
|
||||
async unmount(base, _dispose = true) {
|
||||
base = normalizeBaseKey(base);
|
||||
if (!base || !context.mounts[base]) {
|
||||
return;
|
||||
}
|
||||
if (context.watching && base in context.unwatch) {
|
||||
context.unwatch[base]();
|
||||
delete context.unwatch[base];
|
||||
}
|
||||
if (_dispose) {
|
||||
await dispose(context.mounts[base]);
|
||||
}
|
||||
context.mountpoints = context.mountpoints.filter((key) => key !== base);
|
||||
delete context.mounts[base];
|
||||
}
|
||||
};
|
||||
return storage;
|
||||
}
|
||||
async function snapshot(storage, base) {
|
||||
base = normalizeBaseKey(base);
|
||||
const keys = await storage.getKeys(base);
|
||||
const snapshot2 = {};
|
||||
await Promise.all(keys.map(async (key) => {
|
||||
snapshot2[key.slice(base.length)] = await storage.getItem(key);
|
||||
}));
|
||||
return snapshot2;
|
||||
}
|
||||
async function restoreSnapshot(driver, snapshot2, base = "") {
|
||||
base = normalizeBaseKey(base);
|
||||
await Promise.all(Object.entries(snapshot2).map((e) => driver.setItem(base + e[0], e[1])));
|
||||
}
|
||||
function watch(driver, onChange, base) {
|
||||
return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {
|
||||
};
|
||||
}
|
||||
async function dispose(driver) {
|
||||
if (typeof driver.dispose === "function") {
|
||||
await asyncCall(driver.dispose);
|
||||
}
|
||||
}
|
||||
|
||||
const builtinDrivers = {
|
||||
cloudflareKVHTTP: "unstorage/drivers/cloudflare-kv-http",
|
||||
cloudflareKVBinding: "unstorage/drivers/cloudflare-kv-binding",
|
||||
"cloudflare-kv-http": "unstorage/drivers/cloudflare-kv-http",
|
||||
"cloudflare-kv-binding": "unstorage/drivers/cloudflare-kv-binding",
|
||||
fs: "unstorage/drivers/fs",
|
||||
github: "unstorage/drivers/github",
|
||||
http: "unstorage/drivers/http",
|
||||
localStorage: "unstorage/drivers/localstorage",
|
||||
localstorage: "unstorage/drivers/localstorage",
|
||||
memory: "unstorage/drivers/memory",
|
||||
overlay: "unstorage/drivers/overlay",
|
||||
redis: "unstorage/drivers/redis"
|
||||
};
|
||||
|
||||
export { builtinDrivers, createStorage, defineDriver, joinKeys, normalizeBaseKey, normalizeKey, prefixStorage, restoreSnapshot, snapshot };
|
||||
47
node_modules/unstorage/dist/server.cjs
generated
vendored
Normal file
47
node_modules/unstorage/dist/server.cjs
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const h3 = require('h3');
|
||||
const _utils = require('./shared/unstorage.e5f2cd8b.cjs');
|
||||
|
||||
function createStorageServer(storage, _options = {}) {
|
||||
const app = h3.createApp();
|
||||
app.use(h3.eventHandler(async (event) => {
|
||||
if (event.req.method === "GET") {
|
||||
const value = await storage.getItem(event.req.url);
|
||||
if (!value) {
|
||||
const keys = await storage.getKeys(event.req.url);
|
||||
return keys.map((key) => key.replace(/:/g, "/"));
|
||||
}
|
||||
return _utils.stringify(value);
|
||||
}
|
||||
if (event.req.method === "HEAD") {
|
||||
const _hasItem = await storage.hasItem(event.req.url);
|
||||
event.res.statusCode = _hasItem ? 200 : 404;
|
||||
if (_hasItem) {
|
||||
const meta = await storage.getMeta(event.req.url);
|
||||
if (meta.mtime) {
|
||||
event.res.setHeader("Last-Modified", new Date(meta.mtime).toUTCString());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
if (event.req.method === "PUT") {
|
||||
const value = await h3.readBody(event);
|
||||
await storage.setItem(event.req.url, value);
|
||||
return "OK";
|
||||
}
|
||||
if (event.req.method === "DELETE") {
|
||||
await storage.removeItem(event.req.url);
|
||||
return "OK";
|
||||
}
|
||||
throw h3.createError({
|
||||
statusCode: 405,
|
||||
statusMessage: "Method Not Allowed"
|
||||
});
|
||||
}));
|
||||
return {
|
||||
handle: h3.toNodeListener(app)
|
||||
};
|
||||
}
|
||||
|
||||
exports.createStorageServer = createStorageServer;
|
||||
11
node_modules/unstorage/dist/server.d.ts
generated
vendored
Normal file
11
node_modules/unstorage/dist/server.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { RequestListener } from 'node:http';
|
||||
import { S as Storage } from './types-227df1cc.js';
|
||||
|
||||
interface StorageServerOptions {
|
||||
}
|
||||
interface StorageServer {
|
||||
handle: RequestListener;
|
||||
}
|
||||
declare function createStorageServer(storage: Storage, _options?: StorageServerOptions): StorageServer;
|
||||
|
||||
export { StorageServer, StorageServerOptions, createStorageServer };
|
||||
45
node_modules/unstorage/dist/server.mjs
generated
vendored
Normal file
45
node_modules/unstorage/dist/server.mjs
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import { createApp, eventHandler, readBody, createError, toNodeListener } from 'h3';
|
||||
import { s as stringify } from './shared/unstorage.10149939.mjs';
|
||||
|
||||
function createStorageServer(storage, _options = {}) {
|
||||
const app = createApp();
|
||||
app.use(eventHandler(async (event) => {
|
||||
if (event.req.method === "GET") {
|
||||
const value = await storage.getItem(event.req.url);
|
||||
if (!value) {
|
||||
const keys = await storage.getKeys(event.req.url);
|
||||
return keys.map((key) => key.replace(/:/g, "/"));
|
||||
}
|
||||
return stringify(value);
|
||||
}
|
||||
if (event.req.method === "HEAD") {
|
||||
const _hasItem = await storage.hasItem(event.req.url);
|
||||
event.res.statusCode = _hasItem ? 200 : 404;
|
||||
if (_hasItem) {
|
||||
const meta = await storage.getMeta(event.req.url);
|
||||
if (meta.mtime) {
|
||||
event.res.setHeader("Last-Modified", new Date(meta.mtime).toUTCString());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
if (event.req.method === "PUT") {
|
||||
const value = await readBody(event);
|
||||
await storage.setItem(event.req.url, value);
|
||||
return "OK";
|
||||
}
|
||||
if (event.req.method === "DELETE") {
|
||||
await storage.removeItem(event.req.url);
|
||||
return "OK";
|
||||
}
|
||||
throw createError({
|
||||
statusCode: 405,
|
||||
statusMessage: "Method Not Allowed"
|
||||
});
|
||||
}));
|
||||
return {
|
||||
handle: toNodeListener(app)
|
||||
};
|
||||
}
|
||||
|
||||
export { createStorageServer };
|
||||
22
node_modules/unstorage/dist/shared/unstorage.10149939.mjs
generated
vendored
Normal file
22
node_modules/unstorage/dist/shared/unstorage.10149939.mjs
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
function wrapToPromise(value) {
|
||||
if (!value || typeof value.then !== "function") {
|
||||
return Promise.resolve(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function asyncCall(function_, ...arguments_) {
|
||||
try {
|
||||
return wrapToPromise(function_(...arguments_));
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
function isPrimitive(argument) {
|
||||
const type = typeof argument;
|
||||
return argument === null || type !== "object" && type !== "function";
|
||||
}
|
||||
function stringify(argument) {
|
||||
return isPrimitive(argument) ? argument + "" : JSON.stringify(argument);
|
||||
}
|
||||
|
||||
export { asyncCall as a, stringify as s };
|
||||
25
node_modules/unstorage/dist/shared/unstorage.e5f2cd8b.cjs
generated
vendored
Normal file
25
node_modules/unstorage/dist/shared/unstorage.e5f2cd8b.cjs
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
function wrapToPromise(value) {
|
||||
if (!value || typeof value.then !== "function") {
|
||||
return Promise.resolve(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function asyncCall(function_, ...arguments_) {
|
||||
try {
|
||||
return wrapToPromise(function_(...arguments_));
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
function isPrimitive(argument) {
|
||||
const type = typeof argument;
|
||||
return argument === null || type !== "object" && type !== "function";
|
||||
}
|
||||
function stringify(argument) {
|
||||
return isPrimitive(argument) ? argument + "" : JSON.stringify(argument);
|
||||
}
|
||||
|
||||
exports.asyncCall = asyncCall;
|
||||
exports.stringify = stringify;
|
||||
39
node_modules/unstorage/dist/types-227df1cc.d.ts
generated
vendored
Normal file
39
node_modules/unstorage/dist/types-227df1cc.d.ts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
declare type StorageValue = null | string | String | number | Number | boolean | Boolean | object;
|
||||
declare type WatchEvent = "update" | "remove";
|
||||
declare type WatchCallback = (event: WatchEvent, key: string) => any;
|
||||
declare type MaybePromise<T> = T | Promise<T>;
|
||||
declare type Unwatch = () => MaybePromise<void>;
|
||||
interface StorageMeta {
|
||||
atime?: Date;
|
||||
mtime?: Date;
|
||||
[key: string]: StorageValue | Date | undefined;
|
||||
}
|
||||
interface Driver {
|
||||
hasItem: (key: string) => MaybePromise<boolean>;
|
||||
getItem: (key: string) => StorageValue;
|
||||
setItem?: (key: string, value: string) => MaybePromise<void>;
|
||||
removeItem?: (key: string) => MaybePromise<void>;
|
||||
getMeta?: (key: string) => MaybePromise<StorageMeta>;
|
||||
getKeys: (base?: string) => MaybePromise<string[]>;
|
||||
clear?: () => MaybePromise<void>;
|
||||
dispose?: () => MaybePromise<void>;
|
||||
watch?: (callback: WatchCallback) => MaybePromise<Unwatch>;
|
||||
}
|
||||
interface Storage {
|
||||
hasItem: (key: string) => Promise<boolean>;
|
||||
getItem: (key: string) => Promise<StorageValue>;
|
||||
setItem: (key: string, value: StorageValue) => Promise<void>;
|
||||
removeItem: (key: string, removeMeta?: boolean) => Promise<void>;
|
||||
getMeta: (key: string, nativeMetaOnly?: true) => MaybePromise<StorageMeta>;
|
||||
setMeta: (key: string, value: StorageMeta) => Promise<void>;
|
||||
removeMeta: (key: string) => Promise<void>;
|
||||
getKeys: (base?: string) => Promise<string[]>;
|
||||
clear: (base?: string) => Promise<void>;
|
||||
dispose: () => Promise<void>;
|
||||
watch: (callback: WatchCallback) => Promise<Unwatch>;
|
||||
unwatch: () => Promise<void>;
|
||||
mount: (base: string, driver: Driver) => Storage;
|
||||
unmount: (base: string, dispose?: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
export { Driver as D, Storage as S, Unwatch as U, WatchEvent as W, StorageValue as a, WatchCallback as b, StorageMeta as c };
|
||||
81
node_modules/unstorage/package.json
generated
vendored
Normal file
81
node_modules/unstorage/package.json
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "unstorage",
|
||||
"version": "1.0.1",
|
||||
"description": "Universal Storage Layer",
|
||||
"repository": "unjs/unstorage",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
"./drivers/*": {
|
||||
"import": "./dist/drivers/*.mjs",
|
||||
"require": "./dist/drivers/*.cjs",
|
||||
"types": "./dist/drivers/*.d.ts"
|
||||
},
|
||||
".": {
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"./server": {
|
||||
"import": "./dist/server.mjs",
|
||||
"require": "./dist/server.cjs",
|
||||
"types": "./dist/server.d.ts"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "unbuild",
|
||||
"demo": "vite demo",
|
||||
"dev": "vitest",
|
||||
"doctoc": "doctoc README.md --notitle --maxlevel 3",
|
||||
"lint": "eslint --ext .ts .",
|
||||
"prepack": "pnpm build",
|
||||
"release": "pnpm test && changelogen --release && git push --follow-tags && pnpm publish",
|
||||
"test": "pnpm lint && vitest run --coverage",
|
||||
"unstorage": "pnpm jiti src/cli"
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": "^3.1.2",
|
||||
"chokidar": "^3.5.3",
|
||||
"destr": "^1.2.1",
|
||||
"h3": "^1.0.1",
|
||||
"ioredis": "^5.2.4",
|
||||
"listhen": "^1.0.0",
|
||||
"mkdir": "^0.0.2",
|
||||
"mri": "^1.2.0",
|
||||
"ofetch": "^1.0.0",
|
||||
"ufo": "^1.0.0",
|
||||
"ws": "^8.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^3.18.0",
|
||||
"@types/jsdom": "^20.0.1",
|
||||
"@types/mri": "^1.1.1",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitest/coverage-c8": "^0.25.2",
|
||||
"@vue/compiler-sfc": "^3.2.45",
|
||||
"c8": "^7.12.0",
|
||||
"changelogen": "^0.4.0",
|
||||
"doctoc": "^2.2.1",
|
||||
"eslint": "^8.27.0",
|
||||
"eslint-config-unjs": "^0.0.2",
|
||||
"jiti": "^1.16.0",
|
||||
"jsdom": "^20.0.2",
|
||||
"monaco-editor": "^0.34.1",
|
||||
"msw": "^0.48.2",
|
||||
"types-cloudflare-worker": "^1.2.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "^0.9.4",
|
||||
"vite": "^3.2.3",
|
||||
"vitest": "^0.25.2",
|
||||
"vue": "^3.2.45"
|
||||
},
|
||||
"packageManager": "pnpm@7.16.0"
|
||||
}
|
||||
Reference in New Issue
Block a user