@hocuspocus/extension-s3 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -0
- package/dist/hocuspocus-s3.cjs +129 -0
- package/dist/hocuspocus-s3.cjs.map +1 -0
- package/dist/hocuspocus-s3.esm.js +127 -0
- package/dist/hocuspocus-s3.esm.js.map +1 -0
- package/dist/node_modules/@tiptap/pm/model/index.d.ts +1 -0
- package/dist/node_modules/@tiptap/pm/state/index.d.ts +1 -0
- package/dist/node_modules/@tiptap/pm/transform/index.d.ts +1 -0
- package/dist/node_modules/@tiptap/pm/view/index.d.ts +1 -0
- package/dist/packages/common/src/CloseEvents.d.ts +29 -0
- package/dist/packages/common/src/auth.d.ts +6 -0
- package/dist/packages/common/src/awarenessStatesToArray.d.ts +3 -0
- package/dist/packages/common/src/index.d.ts +4 -0
- package/dist/packages/common/src/types.d.ts +10 -0
- package/dist/packages/extension-database/src/Database.d.ts +30 -0
- package/dist/packages/extension-database/src/index.d.ts +1 -0
- package/dist/packages/extension-logger/src/Logger.d.ts +67 -0
- package/dist/packages/extension-logger/src/index.d.ts +1 -0
- package/dist/packages/extension-redis/src/Redis.d.ts +129 -0
- package/dist/packages/extension-redis/src/index.d.ts +1 -0
- package/dist/packages/extension-s3/src/S3.d.ts +44 -0
- package/dist/packages/extension-s3/src/index.d.ts +1 -0
- package/dist/packages/extension-sqlite/src/SQLite.d.ts +27 -0
- package/dist/packages/extension-sqlite/src/index.d.ts +1 -0
- package/dist/packages/extension-throttle/src/index.d.ts +30 -0
- package/dist/packages/extension-webhook/src/index.d.ts +56 -0
- package/dist/packages/provider/src/EventEmitter.d.ts +9 -0
- package/dist/packages/provider/src/HocuspocusProvider.d.ts +115 -0
- package/dist/packages/provider/src/HocuspocusProviderWebsocket.d.ts +114 -0
- package/dist/packages/provider/src/IncomingMessage.d.ts +17 -0
- package/dist/packages/provider/src/MessageReceiver.d.ts +12 -0
- package/dist/packages/provider/src/MessageSender.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/AuthenticationMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/AwarenessMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/CloseMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/QueryAwarenessMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/StatelessMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/SyncStepOneMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/SyncStepTwoMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/UpdateMessage.d.ts +8 -0
- package/dist/packages/provider/src/index.d.ts +3 -0
- package/dist/packages/provider/src/types.d.ts +92 -0
- package/dist/packages/server/src/ClientConnection.d.ts +63 -0
- package/dist/packages/server/src/Connection.d.ts +62 -0
- package/dist/packages/server/src/DirectConnection.d.ts +14 -0
- package/dist/packages/server/src/Document.d.ts +89 -0
- package/dist/packages/server/src/Hocuspocus.d.ts +77 -0
- package/dist/packages/server/src/IncomingMessage.d.ts +25 -0
- package/dist/packages/server/src/MessageReceiver.d.ts +11 -0
- package/dist/packages/server/src/OutgoingMessage.d.ts +22 -0
- package/dist/packages/server/src/Server.d.ts +32 -0
- package/dist/packages/server/src/index.d.ts +9 -0
- package/dist/packages/server/src/types.d.ts +328 -0
- package/dist/packages/server/src/util/debounce.d.ts +5 -0
- package/dist/packages/server/src/util/getParameters.d.ts +6 -0
- package/dist/packages/transformer/src/Prosemirror.d.ts +11 -0
- package/dist/packages/transformer/src/Tiptap.d.ts +10 -0
- package/dist/packages/transformer/src/index.d.ts +3 -0
- package/dist/packages/transformer/src/types.d.ts +5 -0
- package/dist/playground/backend/src/default.d.ts +1 -0
- package/dist/playground/backend/src/deno.d.ts +1 -0
- package/dist/playground/backend/src/express.d.ts +1 -0
- package/dist/playground/backend/src/hono.d.ts +1 -0
- package/dist/playground/backend/src/koa.d.ts +1 -0
- package/dist/playground/backend/src/load-document.d.ts +1 -0
- package/dist/playground/backend/src/redis.d.ts +1 -0
- package/dist/playground/backend/src/s3-redis.d.ts +1 -0
- package/dist/playground/backend/src/s3.d.ts +1 -0
- package/dist/playground/backend/src/slow.d.ts +1 -0
- package/dist/playground/backend/src/tiptapcollab.d.ts +1 -0
- package/dist/playground/backend/src/webhook.d.ts +1 -0
- package/dist/playground/frontend/app/SocketContext1.d.ts +2 -0
- package/dist/playground/frontend/app/SocketContext2.d.ts +2 -0
- package/dist/playground/frontend/next.config.d.ts +3 -0
- package/dist/tests/extension-database/fetch.d.ts +1 -0
- package/dist/tests/extension-logger/onListen.d.ts +1 -0
- package/dist/tests/extension-redis/onAwarenessChange.d.ts +1 -0
- package/dist/tests/extension-redis/onChange.d.ts +1 -0
- package/dist/tests/extension-redis/onStateless.d.ts +1 -0
- package/dist/tests/extension-redis/onStoreDocument.d.ts +1 -0
- package/dist/tests/extension-s3/fetch.d.ts +1 -0
- package/dist/tests/extension-throttle/banning.d.ts +1 -0
- package/dist/tests/extension-throttle/configuration.d.ts +1 -0
- package/dist/tests/provider/hasUnsyncedChanges.d.ts +1 -0
- package/dist/tests/provider/observe.d.ts +1 -0
- package/dist/tests/provider/observeDeep.d.ts +1 -0
- package/dist/tests/provider/onAuthenticated.d.ts +1 -0
- package/dist/tests/provider/onAuthenticationFailed.d.ts +1 -0
- package/dist/tests/provider/onAwarenessChange.d.ts +1 -0
- package/dist/tests/provider/onAwarenessUpdate.d.ts +1 -0
- package/dist/tests/provider/onClose.d.ts +1 -0
- package/dist/tests/provider/onConnect.d.ts +1 -0
- package/dist/tests/provider/onDisconnect.d.ts +1 -0
- package/dist/tests/provider/onMessage.d.ts +1 -0
- package/dist/tests/provider/onOpen.d.ts +1 -0
- package/dist/tests/provider/onStateless.d.ts +1 -0
- package/dist/tests/provider/onSynced.d.ts +1 -0
- package/dist/tests/providerwebsocket/configuration.d.ts +1 -0
- package/dist/tests/server/address.d.ts +1 -0
- package/dist/tests/server/afterLoadDocument.d.ts +1 -0
- package/dist/tests/server/afterStoreDocument.d.ts +1 -0
- package/dist/tests/server/afterUnloadDocument.d.ts +1 -0
- package/dist/tests/server/beforeBroadcastStateless.d.ts +1 -0
- package/dist/tests/server/beforeHandleMessage.d.ts +1 -0
- package/dist/tests/server/beforeSync.d.ts +1 -0
- package/dist/tests/server/beforeUnloadDocument.d.ts +1 -0
- package/dist/tests/server/closeConnections.d.ts +1 -0
- package/dist/tests/server/getConnectionsCount.d.ts +1 -0
- package/dist/tests/server/getDocumentsCount.d.ts +1 -0
- package/dist/tests/server/listen.d.ts +1 -0
- package/dist/tests/server/onAuthenticate.d.ts +1 -0
- package/dist/tests/server/onAwarenessUpdate.d.ts +1 -0
- package/dist/tests/server/onChange.d.ts +1 -0
- package/dist/tests/server/onClose.d.ts +1 -0
- package/dist/tests/server/onConfigure.d.ts +1 -0
- package/dist/tests/server/onConnect.d.ts +1 -0
- package/dist/tests/server/onDestroy.d.ts +1 -0
- package/dist/tests/server/onDisconnect.d.ts +1 -0
- package/dist/tests/server/onListen.d.ts +1 -0
- package/dist/tests/server/onLoadDocument.d.ts +1 -0
- package/dist/tests/server/onRequest.d.ts +1 -0
- package/dist/tests/server/onStateless.d.ts +1 -0
- package/dist/tests/server/onStoreDocument.d.ts +1 -0
- package/dist/tests/server/onUpgrade.d.ts +1 -0
- package/dist/tests/server/openDirectConnection.d.ts +1 -0
- package/dist/tests/server/websocketError.d.ts +1 -0
- package/dist/tests/transformer/TiptapTransformer.d.ts +1 -0
- package/dist/tests/utils/createDirectory.d.ts +1 -0
- package/dist/tests/utils/flushRedis.d.ts +1 -0
- package/dist/tests/utils/index.d.ts +9 -0
- package/dist/tests/utils/newHocuspocus.d.ts +2 -0
- package/dist/tests/utils/newHocuspocusProvider.d.ts +3 -0
- package/dist/tests/utils/newHocuspocusProviderWebsocket.d.ts +4 -0
- package/dist/tests/utils/randomInteger.d.ts +1 -0
- package/dist/tests/utils/redisConnectionSettings.d.ts +4 -0
- package/dist/tests/utils/removeDirectory.d.ts +1 -0
- package/dist/tests/utils/retryableAssertion.d.ts +2 -0
- package/dist/tests/utils/sleep.d.ts +1 -0
- package/package.json +39 -0
- package/src/S3.ts +178 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const removeDirectory: (dir: string) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sleep: (time: number) => Promise<unknown>;
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hocuspocus/extension-s3",
|
|
3
|
+
"description": "a S3-compatible persistence driver for Hocuspocus",
|
|
4
|
+
"version": "3.2.4",
|
|
5
|
+
"homepage": "https://hocuspocus.dev",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"hocuspocus",
|
|
8
|
+
"yjs",
|
|
9
|
+
"s3",
|
|
10
|
+
"persistence"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "dist/hocuspocus-s3.cjs",
|
|
15
|
+
"module": "dist/hocuspocus-s3.esm.js",
|
|
16
|
+
"types": "dist/packages/extension-s3/src/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
"source": {
|
|
19
|
+
"import": "./src/index.ts"
|
|
20
|
+
},
|
|
21
|
+
"default": {
|
|
22
|
+
"import": "./dist/hocuspocus-s3.esm.js",
|
|
23
|
+
"require": "./dist/hocuspocus-s3.cjs",
|
|
24
|
+
"types": "./dist/packages/extension-s3/src/index.d.ts"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"src",
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "^3.0.0",
|
|
33
|
+
"@hocuspocus/extension-database": "^3.2.4",
|
|
34
|
+
"kleur": "^4.1.4"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/S3.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { DatabaseConfiguration } from "@hocuspocus/extension-database";
|
|
2
|
+
import { Database } from "@hocuspocus/extension-database";
|
|
3
|
+
import { S3Client, GetObjectCommand, PutObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
|
|
4
|
+
import kleur from "kleur";
|
|
5
|
+
|
|
6
|
+
export interface S3Configuration extends DatabaseConfiguration {
|
|
7
|
+
/**
|
|
8
|
+
* AWS S3 region
|
|
9
|
+
*/
|
|
10
|
+
region?: string;
|
|
11
|
+
/**
|
|
12
|
+
* S3 bucket name
|
|
13
|
+
*/
|
|
14
|
+
bucket: string;
|
|
15
|
+
/**
|
|
16
|
+
* S3 key prefix for documents (optional)
|
|
17
|
+
*/
|
|
18
|
+
prefix?: string;
|
|
19
|
+
/**
|
|
20
|
+
* AWS credentials
|
|
21
|
+
*/
|
|
22
|
+
credentials?: {
|
|
23
|
+
accessKeyId: string;
|
|
24
|
+
secretAccessKey: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* S3 endpoint URL (for S3-compatible services like MinIO)
|
|
28
|
+
*/
|
|
29
|
+
endpoint?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Force path style URLs (required for MinIO)
|
|
32
|
+
*/
|
|
33
|
+
forcePathStyle?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Custom S3 client
|
|
36
|
+
*/
|
|
37
|
+
s3Client?: S3Client;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class S3 extends Database {
|
|
41
|
+
private s3Client?: S3Client;
|
|
42
|
+
|
|
43
|
+
configuration: S3Configuration = {
|
|
44
|
+
region: "us-east-1",
|
|
45
|
+
bucket: "",
|
|
46
|
+
prefix: "hocuspocus-documents/",
|
|
47
|
+
forcePathStyle: false,
|
|
48
|
+
fetch: async ({ documentName }) => {
|
|
49
|
+
const key = this.getObjectKey(documentName);
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const command = new GetObjectCommand({
|
|
53
|
+
Bucket: this.configuration.bucket,
|
|
54
|
+
Key: key,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const response = await this.s3Client!.send(command);
|
|
58
|
+
|
|
59
|
+
if (response.Body) {
|
|
60
|
+
// Convert stream to Uint8Array
|
|
61
|
+
const chunks: Uint8Array[] = [];
|
|
62
|
+
const reader = response.Body.transformToWebStream().getReader();
|
|
63
|
+
|
|
64
|
+
while (true) {
|
|
65
|
+
const { done, value } = await reader.read();
|
|
66
|
+
if (done) break;
|
|
67
|
+
chunks.push(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Combine all chunks into a single Uint8Array
|
|
71
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
72
|
+
const result = new Uint8Array(totalLength);
|
|
73
|
+
let offset = 0;
|
|
74
|
+
|
|
75
|
+
for (const chunk of chunks) {
|
|
76
|
+
result.set(chunk, offset);
|
|
77
|
+
offset += chunk.length;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return null;
|
|
84
|
+
} catch (error: any) {
|
|
85
|
+
if (error.name === 'NoSuchKey' || error.$metadata?.httpStatusCode === 404) {
|
|
86
|
+
// Document doesn't exist yet, return null
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
store: async ({ documentName, state }) => {
|
|
93
|
+
const key = this.getObjectKey(documentName);
|
|
94
|
+
|
|
95
|
+
const command = new PutObjectCommand({
|
|
96
|
+
Bucket: this.configuration.bucket,
|
|
97
|
+
Key: key,
|
|
98
|
+
Body: state,
|
|
99
|
+
ContentType: "application/octet-stream",
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await this.s3Client!.send(command);
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
constructor(configuration: Partial<S3Configuration>) {
|
|
107
|
+
super({});
|
|
108
|
+
|
|
109
|
+
this.configuration = {
|
|
110
|
+
...this.configuration,
|
|
111
|
+
...configuration,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Validate required configuration
|
|
115
|
+
if (!this.configuration.bucket) {
|
|
116
|
+
throw new Error("S3 bucket name is required");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private getObjectKey(documentName: string): string {
|
|
121
|
+
const prefix = this.configuration.prefix || "";
|
|
122
|
+
return `${prefix}${documentName}.bin`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async onConfigure() {
|
|
126
|
+
// Use custom S3 client if provided, otherwise create one
|
|
127
|
+
if (this.configuration.s3Client) {
|
|
128
|
+
this.s3Client = this.configuration.s3Client;
|
|
129
|
+
} else {
|
|
130
|
+
const clientConfig: any = {
|
|
131
|
+
region: this.configuration.region,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (this.configuration.credentials) {
|
|
135
|
+
clientConfig.credentials = this.configuration.credentials;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (this.configuration.endpoint) {
|
|
139
|
+
clientConfig.endpoint = this.configuration.endpoint;
|
|
140
|
+
clientConfig.forcePathStyle = this.configuration.forcePathStyle;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.s3Client = new S3Client(clientConfig);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Test S3 connection by checking if bucket exists
|
|
147
|
+
try {
|
|
148
|
+
const command = new HeadObjectCommand({
|
|
149
|
+
Bucket: this.configuration.bucket,
|
|
150
|
+
Key: "test-connection", // This will likely return 404, but that's fine
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await this.s3Client.send(command);
|
|
154
|
+
} catch (error: any) {
|
|
155
|
+
// 404 is expected for the test key, any other error indicates connection issues
|
|
156
|
+
if (error.$metadata?.httpStatusCode !== 404) {
|
|
157
|
+
// Don't show credential errors as connection failures in development
|
|
158
|
+
if (error.message?.includes('Could not load credentials')) {
|
|
159
|
+
console.warn(` ${kleur.yellow("S3 warning:")} ${error.message}`);
|
|
160
|
+
console.warn(` ${kleur.yellow("Note:")} Ensure AWS credentials are properly configured for production use`);
|
|
161
|
+
} else {
|
|
162
|
+
console.error(` ${kleur.red("S3 connection failed:")} ${error.message}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async onListen() {
|
|
169
|
+
const endpoint = this.configuration.endpoint || `https://s3.${this.configuration.region}.amazonaws.com`;
|
|
170
|
+
console.log(
|
|
171
|
+
` ${kleur.green("S3 extension configured:")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`,
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (this.configuration.prefix) {
|
|
175
|
+
console.log(` ${kleur.blue("S3 key prefix:")} ${this.configuration.prefix}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./S3.ts";
|