snapshot of https://github.com/ueberdosis/hocuspocus.git @ cf3cfa355b4d3bb61c6b6c80071f71783e32470e (2026-09-15)
Some checks failed
build / lint (22) (push) Failing after 17s
build / test (22) (push) Failing after 8s
build / lint (23) (push) Failing after 2s
build / build (22) (push) Has been skipped
build / build (23) (push) Has been skipped
build / test (23) (push) Failing after 4s
docsearch / docsearch (push) Failing after 1s
Some checks failed
build / lint (22) (push) Failing after 17s
build / test (22) (push) Failing after 8s
build / lint (23) (push) Failing after 2s
build / build (22) (push) Has been skipped
build / build (23) (push) Has been skipped
build / test (23) (push) Failing after 4s
docsearch / docsearch (push) Failing after 1s
This commit is contained in:
1273
packages/extension-sqlite/CHANGELOG.md
Normal file
1273
packages/extension-sqlite/CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
55
packages/extension-sqlite/README.md
Normal file
55
packages/extension-sqlite/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# @hocuspocus/extension-sqlite
|
||||
[](https://www.npmjs.com/package/@hocuspocus/extension-sqlite)
|
||||
[](https://npmcharts.com/compare/tiptap?minimal=true)
|
||||
[](https://www.npmjs.com/package/@hocuspocus/extension-sqlite)
|
||||
[](https://github.com/sponsors/ueberdosis)
|
||||
|
||||
Persist [Hocuspocus](https://github.com/ueberdosis/hocuspocus) documents to a local SQLite database. Zero-config storage for development, self-hosted single-instance deployments, and small production setups. Uses [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @hocuspocus/extension-sqlite
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { Server } from "@hocuspocus/server"
|
||||
import { SQLite } from "@hocuspocus/extension-sqlite"
|
||||
|
||||
const server = new Server({
|
||||
extensions: [
|
||||
new SQLite({ database: "db.sqlite" }),
|
||||
],
|
||||
})
|
||||
|
||||
server.listen()
|
||||
```
|
||||
|
||||
`database` accepts:
|
||||
- a filename (persisted to disk, e.g. `"db.sqlite"`)
|
||||
- `":memory:"` for an in-memory database
|
||||
- `""` for an anonymous on-disk database
|
||||
|
||||
Omit the option entirely to default to `":memory:"`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `Could not locate the bindings file`
|
||||
|
||||
`better-sqlite3` ships prebuilt native addons, but they don't always cover the newest Node.js release on day one. Rebuild from source in your server project:
|
||||
|
||||
```bash
|
||||
npm rebuild better-sqlite3 --build-from-source
|
||||
```
|
||||
|
||||
Needs a C++ toolchain (Xcode Command Line Tools on macOS, `build-essential` on Debian/Ubuntu, Visual Studio Build Tools on Windows).
|
||||
|
||||
## Documentation
|
||||
|
||||
Schema, custom `fetch`/`store`, and migration guides: [tiptap.dev/docs/hocuspocus/server/extensions/sqlite](https://tiptap.dev/docs/hocuspocus/server/extensions/sqlite).
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE.md](https://github.com/ueberdosis/hocuspocus/blob/main/LICENSE.md).
|
||||
44
packages/extension-sqlite/package.json
Normal file
44
packages/extension-sqlite/package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@hocuspocus/extension-sqlite",
|
||||
"description": "a generic Hocuspocus persistence driver for the sqlite",
|
||||
"version": "4.7.0",
|
||||
"homepage": "https://hocuspocus.dev",
|
||||
"keywords": [
|
||||
"hocuspocus",
|
||||
"yjs"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "dist/hocuspocus-sqlite.cjs",
|
||||
"module": "dist/hocuspocus-sqlite.esm.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
"source": {
|
||||
"import": "./src/index.ts"
|
||||
},
|
||||
"default": {
|
||||
"import": "./dist/hocuspocus-sqlite.esm.js",
|
||||
"require": "./dist/hocuspocus-sqlite.cjs",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hocuspocus/extension-database": "workspace:^",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"kleur": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.13"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "b3454a4ca289a84ddfb7fa5607a2d4b8d5c37e9d",
|
||||
"repository": {
|
||||
"url": "https://github.com/ueberdosis/hocuspocus"
|
||||
}
|
||||
}
|
||||
81
packages/extension-sqlite/src/SQLite.ts
Normal file
81
packages/extension-sqlite/src/SQLite.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import type { DatabaseConfiguration } from "@hocuspocus/extension-database";
|
||||
import { Database } from "@hocuspocus/extension-database";
|
||||
import BetterSqlite3 from "better-sqlite3";
|
||||
import kleur from "kleur";
|
||||
|
||||
export const schema = `CREATE TABLE IF NOT EXISTS "documents" (
|
||||
"name" varchar(255) NOT NULL,
|
||||
"data" blob NOT NULL,
|
||||
UNIQUE(name)
|
||||
)`;
|
||||
|
||||
export const selectQuery = `
|
||||
SELECT data FROM "documents" WHERE name = $name ORDER BY rowid DESC
|
||||
`;
|
||||
|
||||
export const upsertQuery = `
|
||||
INSERT INTO "documents" ("name", "data") VALUES ($name, $data)
|
||||
ON CONFLICT(name) DO UPDATE SET data = $data
|
||||
`;
|
||||
|
||||
const SQLITE_INMEMORY = ":memory:";
|
||||
|
||||
export interface SQLiteConfiguration extends DatabaseConfiguration {
|
||||
/**
|
||||
* Valid values are filenames, ":memory:" for an anonymous in-memory database and an empty
|
||||
* string for an anonymous disk-based database. Anonymous databases are not persisted and
|
||||
* when closing the database handle, their contents are lost.
|
||||
*
|
||||
* https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md#new-daboratabasepath-options
|
||||
*/
|
||||
database: string;
|
||||
/**
|
||||
* The database schema to create.
|
||||
*/
|
||||
schema: string;
|
||||
}
|
||||
|
||||
export class SQLite extends Database {
|
||||
db?: BetterSqlite3.Database;
|
||||
|
||||
configuration: SQLiteConfiguration = {
|
||||
database: SQLITE_INMEMORY,
|
||||
schema,
|
||||
fetch: async ({ documentName }) => {
|
||||
const row = this.db
|
||||
?.prepare(selectQuery)
|
||||
.get({ name: documentName }) as { data: Buffer } | undefined;
|
||||
|
||||
return row?.data ?? null;
|
||||
},
|
||||
store: async ({ documentName, state }) => {
|
||||
this.db?.prepare(upsertQuery).run({
|
||||
name: documentName,
|
||||
data: state,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
constructor(configuration?: Partial<SQLiteConfiguration>) {
|
||||
super({});
|
||||
|
||||
this.configuration = {
|
||||
...this.configuration,
|
||||
...configuration,
|
||||
};
|
||||
}
|
||||
|
||||
async onConfigure() {
|
||||
this.db = new BetterSqlite3(this.configuration.database);
|
||||
this.db.exec(this.configuration.schema);
|
||||
}
|
||||
|
||||
async onListen() {
|
||||
if (this.configuration.database === SQLITE_INMEMORY) {
|
||||
console.warn(
|
||||
` ${kleur.yellow("The SQLite extension is configured as an in-memory database. All changes will be lost on restart!")}`,
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
}
|
||||
}
|
||||
1
packages/extension-sqlite/src/index.ts
Normal file
1
packages/extension-sqlite/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./SQLite.ts";
|
||||
Reference in New Issue
Block a user