@hocuspocus/extension-s3 3.4.4 → 3.4.5-rc.0

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.
Files changed (142) hide show
  1. package/dist/hocuspocus-s3.cjs +123 -127
  2. package/dist/hocuspocus-s3.cjs.map +1 -1
  3. package/dist/hocuspocus-s3.esm.js +95 -126
  4. package/dist/hocuspocus-s3.esm.js.map +1 -1
  5. package/dist/index.d.ts +47 -0
  6. package/dist/index.js +97 -0
  7. package/package.json +5 -5
  8. package/dist/node_modules/@tiptap/pm/model/index.d.ts +0 -1
  9. package/dist/node_modules/@tiptap/pm/state/index.d.ts +0 -1
  10. package/dist/node_modules/@tiptap/pm/transform/index.d.ts +0 -1
  11. package/dist/node_modules/@tiptap/pm/view/index.d.ts +0 -1
  12. package/dist/packages/common/src/CloseEvents.d.ts +0 -29
  13. package/dist/packages/common/src/auth.d.ts +0 -13
  14. package/dist/packages/common/src/awarenessStatesToArray.d.ts +0 -3
  15. package/dist/packages/common/src/index.d.ts +0 -4
  16. package/dist/packages/common/src/types.d.ts +0 -10
  17. package/dist/packages/extension-database/src/Database.d.ts +0 -30
  18. package/dist/packages/extension-database/src/index.d.ts +0 -1
  19. package/dist/packages/extension-logger/src/Logger.d.ts +0 -67
  20. package/dist/packages/extension-logger/src/index.d.ts +0 -1
  21. package/dist/packages/extension-redis/src/Redis.d.ts +0 -124
  22. package/dist/packages/extension-redis/src/index.d.ts +0 -1
  23. package/dist/packages/extension-s3/src/S3.d.ts +0 -44
  24. package/dist/packages/extension-s3/src/index.d.ts +0 -1
  25. package/dist/packages/extension-sqlite/src/SQLite.d.ts +0 -27
  26. package/dist/packages/extension-sqlite/src/index.d.ts +0 -1
  27. package/dist/packages/extension-throttle/src/index.d.ts +0 -30
  28. package/dist/packages/extension-webhook/src/index.d.ts +0 -56
  29. package/dist/packages/provider/src/EventEmitter.d.ts +0 -9
  30. package/dist/packages/provider/src/HocuspocusProvider.d.ts +0 -116
  31. package/dist/packages/provider/src/HocuspocusProviderWebsocket.d.ts +0 -119
  32. package/dist/packages/provider/src/IncomingMessage.d.ts +0 -17
  33. package/dist/packages/provider/src/MessageReceiver.d.ts +0 -12
  34. package/dist/packages/provider/src/MessageSender.d.ts +0 -9
  35. package/dist/packages/provider/src/OutgoingMessage.d.ts +0 -9
  36. package/dist/packages/provider/src/OutgoingMessages/AuthenticationMessage.d.ts +0 -8
  37. package/dist/packages/provider/src/OutgoingMessages/AwarenessMessage.d.ts +0 -9
  38. package/dist/packages/provider/src/OutgoingMessages/CloseMessage.d.ts +0 -9
  39. package/dist/packages/provider/src/OutgoingMessages/QueryAwarenessMessage.d.ts +0 -9
  40. package/dist/packages/provider/src/OutgoingMessages/StatelessMessage.d.ts +0 -8
  41. package/dist/packages/provider/src/OutgoingMessages/SyncStepOneMessage.d.ts +0 -9
  42. package/dist/packages/provider/src/OutgoingMessages/SyncStepTwoMessage.d.ts +0 -9
  43. package/dist/packages/provider/src/OutgoingMessages/UpdateMessage.d.ts +0 -8
  44. package/dist/packages/provider/src/index.d.ts +0 -3
  45. package/dist/packages/provider/src/types.d.ts +0 -93
  46. package/dist/packages/server/src/ClientConnection.d.ts +0 -63
  47. package/dist/packages/server/src/Connection.d.ts +0 -75
  48. package/dist/packages/server/src/DirectConnection.d.ts +0 -14
  49. package/dist/packages/server/src/Document.d.ts +0 -92
  50. package/dist/packages/server/src/Hocuspocus.d.ts +0 -80
  51. package/dist/packages/server/src/IncomingMessage.d.ts +0 -25
  52. package/dist/packages/server/src/MessageReceiver.d.ts +0 -11
  53. package/dist/packages/server/src/OutgoingMessage.d.ts +0 -23
  54. package/dist/packages/server/src/Server.d.ts +0 -32
  55. package/dist/packages/server/src/index.d.ts +0 -9
  56. package/dist/packages/server/src/types.d.ts +0 -342
  57. package/dist/packages/server/src/util/debounce.d.ts +0 -6
  58. package/dist/packages/server/src/util/getParameters.d.ts +0 -6
  59. package/dist/packages/transformer/src/Prosemirror.d.ts +0 -11
  60. package/dist/packages/transformer/src/Tiptap.d.ts +0 -10
  61. package/dist/packages/transformer/src/index.d.ts +0 -3
  62. package/dist/packages/transformer/src/types.d.ts +0 -5
  63. package/dist/playground/backend/src/default.d.ts +0 -1
  64. package/dist/playground/backend/src/deno.d.ts +0 -1
  65. package/dist/playground/backend/src/express.d.ts +0 -1
  66. package/dist/playground/backend/src/hono.d.ts +0 -1
  67. package/dist/playground/backend/src/koa.d.ts +0 -1
  68. package/dist/playground/backend/src/load-document.d.ts +0 -1
  69. package/dist/playground/backend/src/redis.d.ts +0 -1
  70. package/dist/playground/backend/src/s3-redis.d.ts +0 -1
  71. package/dist/playground/backend/src/s3.d.ts +0 -1
  72. package/dist/playground/backend/src/slow.d.ts +0 -1
  73. package/dist/playground/backend/src/tiptapcollab.d.ts +0 -1
  74. package/dist/playground/backend/src/webhook.d.ts +0 -1
  75. package/dist/playground/frontend/app/SocketContext1.d.ts +0 -2
  76. package/dist/playground/frontend/app/SocketContext2.d.ts +0 -2
  77. package/dist/playground/frontend/next.config.d.ts +0 -3
  78. package/dist/tests/extension-database/fetch.d.ts +0 -1
  79. package/dist/tests/extension-logger/onListen.d.ts +0 -1
  80. package/dist/tests/extension-redis/onAwarenessChange.d.ts +0 -1
  81. package/dist/tests/extension-redis/onChange.d.ts +0 -1
  82. package/dist/tests/extension-redis/onStateless.d.ts +0 -1
  83. package/dist/tests/extension-redis/onStoreDocument.d.ts +0 -1
  84. package/dist/tests/extension-s3/fetch.d.ts +0 -1
  85. package/dist/tests/extension-throttle/banning.d.ts +0 -1
  86. package/dist/tests/extension-throttle/configuration.d.ts +0 -1
  87. package/dist/tests/provider/hasUnsyncedChanges.d.ts +0 -1
  88. package/dist/tests/provider/observe.d.ts +0 -1
  89. package/dist/tests/provider/observeDeep.d.ts +0 -1
  90. package/dist/tests/provider/onAuthenticated.d.ts +0 -1
  91. package/dist/tests/provider/onAuthenticationFailed.d.ts +0 -1
  92. package/dist/tests/provider/onAwarenessChange.d.ts +0 -1
  93. package/dist/tests/provider/onAwarenessUpdate.d.ts +0 -1
  94. package/dist/tests/provider/onClose.d.ts +0 -1
  95. package/dist/tests/provider/onConnect.d.ts +0 -1
  96. package/dist/tests/provider/onDisconnect.d.ts +0 -1
  97. package/dist/tests/provider/onMessage.d.ts +0 -1
  98. package/dist/tests/provider/onOpen.d.ts +0 -1
  99. package/dist/tests/provider/onStateless.d.ts +0 -1
  100. package/dist/tests/provider/onSynced.d.ts +0 -1
  101. package/dist/tests/providerwebsocket/configuration.d.ts +0 -1
  102. package/dist/tests/server/address.d.ts +0 -1
  103. package/dist/tests/server/afterLoadDocument.d.ts +0 -1
  104. package/dist/tests/server/afterStoreDocument.d.ts +0 -1
  105. package/dist/tests/server/afterUnloadDocument.d.ts +0 -1
  106. package/dist/tests/server/beforeBroadcastStateless.d.ts +0 -1
  107. package/dist/tests/server/beforeHandleMessage.d.ts +0 -1
  108. package/dist/tests/server/beforeSync.d.ts +0 -1
  109. package/dist/tests/server/beforeUnloadDocument.d.ts +0 -1
  110. package/dist/tests/server/closeConnections.d.ts +0 -1
  111. package/dist/tests/server/getConnectionsCount.d.ts +0 -1
  112. package/dist/tests/server/getDocumentsCount.d.ts +0 -1
  113. package/dist/tests/server/listen.d.ts +0 -1
  114. package/dist/tests/server/onAuthenticate.d.ts +0 -1
  115. package/dist/tests/server/onAwarenessUpdate.d.ts +0 -1
  116. package/dist/tests/server/onChange.d.ts +0 -1
  117. package/dist/tests/server/onClose.d.ts +0 -1
  118. package/dist/tests/server/onConfigure.d.ts +0 -1
  119. package/dist/tests/server/onConnect.d.ts +0 -1
  120. package/dist/tests/server/onDestroy.d.ts +0 -1
  121. package/dist/tests/server/onDisconnect.d.ts +0 -1
  122. package/dist/tests/server/onListen.d.ts +0 -1
  123. package/dist/tests/server/onLoadDocument.d.ts +0 -1
  124. package/dist/tests/server/onRequest.d.ts +0 -1
  125. package/dist/tests/server/onStateless.d.ts +0 -1
  126. package/dist/tests/server/onStoreDocument.d.ts +0 -1
  127. package/dist/tests/server/onTokenSync.d.ts +0 -1
  128. package/dist/tests/server/onUpgrade.d.ts +0 -1
  129. package/dist/tests/server/openDirectConnection.d.ts +0 -1
  130. package/dist/tests/server/websocketError.d.ts +0 -1
  131. package/dist/tests/transformer/TiptapTransformer.d.ts +0 -1
  132. package/dist/tests/utils/createDirectory.d.ts +0 -1
  133. package/dist/tests/utils/flushRedis.d.ts +0 -1
  134. package/dist/tests/utils/index.d.ts +0 -9
  135. package/dist/tests/utils/newHocuspocus.d.ts +0 -2
  136. package/dist/tests/utils/newHocuspocusProvider.d.ts +0 -3
  137. package/dist/tests/utils/newHocuspocusProviderWebsocket.d.ts +0 -4
  138. package/dist/tests/utils/randomInteger.d.ts +0 -1
  139. package/dist/tests/utils/redisConnectionSettings.d.ts +0 -4
  140. package/dist/tests/utils/removeDirectory.d.ts +0 -1
  141. package/dist/tests/utils/retryableAssertion.d.ts +0 -2
  142. package/dist/tests/utils/sleep.d.ts +0 -1
@@ -1,131 +1,127 @@
1
- 'use strict';
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
2
27
 
3
- var extensionDatabase = require('@hocuspocus/extension-database');
4
- var clientS3 = require('@aws-sdk/client-s3');
5
- var kleur = require('kleur');
28
+ //#endregion
29
+ let _hocuspocus_extension_database = require("@hocuspocus/extension-database");
30
+ let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
31
+ let kleur = require("kleur");
32
+ kleur = __toESM(kleur);
6
33
 
7
- class S3 extends extensionDatabase.Database {
8
- constructor(configuration) {
9
- super({});
10
- this.configuration = {
11
- region: "us-east-1",
12
- bucket: "",
13
- prefix: "hocuspocus-documents/",
14
- forcePathStyle: false,
15
- fetch: async ({ documentName }) => {
16
- var _a;
17
- const key = this.getObjectKey(documentName);
18
- try {
19
- const command = new clientS3.GetObjectCommand({
20
- Bucket: this.configuration.bucket,
21
- Key: key,
22
- });
23
- const response = await this.s3Client.send(command);
24
- if (response.Body) {
25
- // Convert stream to Uint8Array
26
- const chunks = [];
27
- const reader = response.Body.transformToWebStream().getReader();
28
- while (true) {
29
- const { done, value } = await reader.read();
30
- if (done)
31
- break;
32
- chunks.push(value);
33
- }
34
- // Combine all chunks into a single Uint8Array
35
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
36
- const result = new Uint8Array(totalLength);
37
- let offset = 0;
38
- for (const chunk of chunks) {
39
- result.set(chunk, offset);
40
- offset += chunk.length;
41
- }
42
- return result;
43
- }
44
- return null;
45
- }
46
- catch (error) {
47
- if (error.name === "NoSuchKey" ||
48
- ((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404) {
49
- // Document doesn't exist yet, return null
50
- return null;
51
- }
52
- throw error;
53
- }
54
- },
55
- store: async ({ documentName, state }) => {
56
- const key = this.getObjectKey(documentName);
57
- const command = new clientS3.PutObjectCommand({
58
- Bucket: this.configuration.bucket,
59
- Key: key,
60
- Body: state,
61
- ContentType: "application/octet-stream",
62
- });
63
- await this.s3Client.send(command);
64
- },
65
- };
66
- this.configuration = {
67
- ...this.configuration,
68
- ...configuration,
69
- };
70
- // Validate required configuration
71
- if (!this.configuration.bucket) {
72
- throw new Error("S3 bucket name is required");
73
- }
74
- }
75
- getObjectKey(documentName) {
76
- const prefix = this.configuration.prefix || "";
77
- return `${prefix}${documentName}.bin`;
78
- }
79
- async onConfigure() {
80
- var _a, _b;
81
- // Use custom S3 client if provided, otherwise create one
82
- if (this.configuration.s3Client) {
83
- this.s3Client = this.configuration.s3Client;
84
- }
85
- else {
86
- const clientConfig = {
87
- region: this.configuration.region,
88
- };
89
- if (this.configuration.credentials) {
90
- clientConfig.credentials = this.configuration.credentials;
91
- }
92
- if (this.configuration.endpoint) {
93
- clientConfig.endpoint = this.configuration.endpoint;
94
- clientConfig.forcePathStyle = this.configuration.forcePathStyle;
95
- }
96
- this.s3Client = new clientS3.S3Client(clientConfig);
97
- }
98
- // Test S3 connection by checking if bucket exists
99
- try {
100
- const command = new clientS3.HeadObjectCommand({
101
- Bucket: this.configuration.bucket,
102
- Key: "test-connection", // This will likely return 404, but that's fine
103
- });
104
- await this.s3Client.send(command);
105
- }
106
- catch (error) {
107
- // 404 is expected for the test key, any other error indicates connection issues
108
- if (((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== 404) {
109
- // Don't show credential errors as connection failures in development
110
- if ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes("Could not load credentials")) {
111
- console.warn(` ${kleur.yellow("S3 warning:")} ${error.message}`);
112
- console.warn(` ${kleur.yellow("Note:")} Ensure AWS credentials are properly configured for production use`);
113
- }
114
- else {
115
- console.error(` ${kleur.red("S3 connection failed:")} ${error.message}`);
116
- }
117
- }
118
- }
119
- }
120
- async onListen() {
121
- const endpoint = this.configuration.endpoint ||
122
- `https://s3.${this.configuration.region}.amazonaws.com`;
123
- console.log(` ${kleur.green("S3 extension configured:")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`);
124
- if (this.configuration.prefix) {
125
- console.log(` ${kleur.blue("S3 key prefix:")} ${this.configuration.prefix}`);
126
- }
127
- }
128
- }
34
+ //#region packages/extension-s3/src/S3.ts
35
+ var S3 = class extends _hocuspocus_extension_database.Database {
36
+ constructor(configuration) {
37
+ super({});
38
+ this.configuration = {
39
+ region: "us-east-1",
40
+ bucket: "",
41
+ prefix: "hocuspocus-documents/",
42
+ forcePathStyle: false,
43
+ fetch: async ({ documentName }) => {
44
+ const key = this.getObjectKey(documentName);
45
+ try {
46
+ const command = new _aws_sdk_client_s3.GetObjectCommand({
47
+ Bucket: this.configuration.bucket,
48
+ Key: key
49
+ });
50
+ const response = await this.s3Client.send(command);
51
+ if (response.Body) {
52
+ const chunks = [];
53
+ const reader = response.Body.transformToWebStream().getReader();
54
+ while (true) {
55
+ const { done, value } = await reader.read();
56
+ if (done) break;
57
+ chunks.push(value);
58
+ }
59
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
60
+ const result = new Uint8Array(totalLength);
61
+ let offset = 0;
62
+ for (const chunk of chunks) {
63
+ result.set(chunk, offset);
64
+ offset += chunk.length;
65
+ }
66
+ return result;
67
+ }
68
+ return null;
69
+ } catch (error) {
70
+ if (error.name === "NoSuchKey" || error.$metadata?.httpStatusCode === 404) return null;
71
+ throw error;
72
+ }
73
+ },
74
+ store: async ({ documentName, state }) => {
75
+ const key = this.getObjectKey(documentName);
76
+ const command = new _aws_sdk_client_s3.PutObjectCommand({
77
+ Bucket: this.configuration.bucket,
78
+ Key: key,
79
+ Body: state,
80
+ ContentType: "application/octet-stream"
81
+ });
82
+ await this.s3Client.send(command);
83
+ }
84
+ };
85
+ this.configuration = {
86
+ ...this.configuration,
87
+ ...configuration
88
+ };
89
+ if (!this.configuration.bucket) throw new Error("S3 bucket name is required");
90
+ }
91
+ getObjectKey(documentName) {
92
+ return `${this.configuration.prefix || ""}${documentName}.bin`;
93
+ }
94
+ async onConfigure() {
95
+ if (this.configuration.s3Client) this.s3Client = this.configuration.s3Client;
96
+ else {
97
+ const clientConfig = { region: this.configuration.region };
98
+ if (this.configuration.credentials) clientConfig.credentials = this.configuration.credentials;
99
+ if (this.configuration.endpoint) {
100
+ clientConfig.endpoint = this.configuration.endpoint;
101
+ clientConfig.forcePathStyle = this.configuration.forcePathStyle;
102
+ }
103
+ this.s3Client = new _aws_sdk_client_s3.S3Client(clientConfig);
104
+ }
105
+ try {
106
+ const command = new _aws_sdk_client_s3.HeadObjectCommand({
107
+ Bucket: this.configuration.bucket,
108
+ Key: "test-connection"
109
+ });
110
+ await this.s3Client.send(command);
111
+ } catch (error) {
112
+ if (error.$metadata?.httpStatusCode !== 404) if (error.message?.includes("Could not load credentials")) {
113
+ console.warn(` ${kleur.default.yellow("S3 warning:")} ${error.message}`);
114
+ console.warn(` ${kleur.default.yellow("Note:")} Ensure AWS credentials are properly configured for production use`);
115
+ } else console.error(` ${kleur.default.red("S3 connection failed:")} ${error.message}`);
116
+ }
117
+ }
118
+ async onListen() {
119
+ const endpoint = this.configuration.endpoint || `https://s3.${this.configuration.region}.amazonaws.com`;
120
+ console.log(` ${kleur.default.green("S3 extension configured:")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`);
121
+ if (this.configuration.prefix) console.log(` ${kleur.default.blue("S3 key prefix:")} ${this.configuration.prefix}`);
122
+ }
123
+ };
129
124
 
125
+ //#endregion
130
126
  exports.S3 = S3;
131
- //# sourceMappingURL=hocuspocus-s3.cjs.map
127
+ //# sourceMappingURL=hocuspocus-s3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"hocuspocus-s3.cjs","sources":["../src/S3.ts"],"sourcesContent":[null],"names":["Database","GetObjectCommand","PutObjectCommand","S3Client","HeadObjectCommand"],"mappings":"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"}
1
+ {"version":3,"file":"hocuspocus-s3.cjs","names":["Database","GetObjectCommand","PutObjectCommand","S3Client","HeadObjectCommand"],"sources":["../src/S3.ts"],"sourcesContent":["import type { DatabaseConfiguration } from \"@hocuspocus/extension-database\";\nimport { Database } from \"@hocuspocus/extension-database\";\nimport {\n\tS3Client,\n\tGetObjectCommand,\n\tPutObjectCommand,\n\tHeadObjectCommand,\n} from \"@aws-sdk/client-s3\";\nimport kleur from \"kleur\";\n\nexport interface S3Configuration extends DatabaseConfiguration {\n\t/**\n\t * AWS S3 region\n\t */\n\tregion?: string;\n\t/**\n\t * S3 bucket name\n\t */\n\tbucket: string;\n\t/**\n\t * S3 key prefix for documents (optional)\n\t */\n\tprefix?: string;\n\t/**\n\t * AWS credentials\n\t */\n\tcredentials?: {\n\t\taccessKeyId: string;\n\t\tsecretAccessKey: string;\n\t};\n\t/**\n\t * S3 endpoint URL (for S3-compatible services like MinIO)\n\t */\n\tendpoint?: string;\n\t/**\n\t * Force path style URLs (required for MinIO)\n\t */\n\tforcePathStyle?: boolean;\n\t/**\n\t * Custom S3 client\n\t */\n\ts3Client?: S3Client;\n}\n\nexport class S3 extends Database {\n\tprivate s3Client?: S3Client;\n\n\tconfiguration: S3Configuration = {\n\t\tregion: \"us-east-1\",\n\t\tbucket: \"\",\n\t\tprefix: \"hocuspocus-documents/\",\n\t\tforcePathStyle: false,\n\t\tfetch: async ({ documentName }) => {\n\t\t\tconst key = this.getObjectKey(documentName);\n\n\t\t\ttry {\n\t\t\t\tconst command = new GetObjectCommand({\n\t\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\t\tKey: key,\n\t\t\t\t});\n\n\t\t\t\tconst response = await this.s3Client!.send(command);\n\n\t\t\t\tif (response.Body) {\n\t\t\t\t\t// Convert stream to Uint8Array\n\t\t\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\t\t\tconst reader = response.Body.transformToWebStream().getReader();\n\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) break;\n\t\t\t\t\t\tchunks.push(value);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Combine all chunks into a single Uint8Array\n\t\t\t\t\tconst totalLength = chunks.reduce(\n\t\t\t\t\t\t(acc, chunk) => acc + chunk.length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t\tconst result = new Uint8Array(totalLength);\n\t\t\t\t\tlet offset = 0;\n\n\t\t\t\t\tfor (const chunk of chunks) {\n\t\t\t\t\t\tresult.set(chunk, offset);\n\t\t\t\t\t\toffset += chunk.length;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t} catch (error: any) {\n\t\t\t\tif (\n\t\t\t\t\terror.name === \"NoSuchKey\" ||\n\t\t\t\t\terror.$metadata?.httpStatusCode === 404\n\t\t\t\t) {\n\t\t\t\t\t// Document doesn't exist yet, return null\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tstore: async ({ documentName, state }) => {\n\t\t\tconst key = this.getObjectKey(documentName);\n\n\t\t\tconst command = new PutObjectCommand({\n\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\tKey: key,\n\t\t\t\tBody: state,\n\t\t\t\tContentType: \"application/octet-stream\",\n\t\t\t});\n\n\t\t\tawait this.s3Client!.send(command);\n\t\t},\n\t};\n\n\tconstructor(configuration: Partial<S3Configuration>) {\n\t\tsuper({});\n\n\t\tthis.configuration = {\n\t\t\t...this.configuration,\n\t\t\t...configuration,\n\t\t};\n\n\t\t// Validate required configuration\n\t\tif (!this.configuration.bucket) {\n\t\t\tthrow new Error(\"S3 bucket name is required\");\n\t\t}\n\t}\n\n\tprivate getObjectKey(documentName: string): string {\n\t\tconst prefix = this.configuration.prefix || \"\";\n\t\treturn `${prefix}${documentName}.bin`;\n\t}\n\n\tasync onConfigure() {\n\t\t// Use custom S3 client if provided, otherwise create one\n\t\tif (this.configuration.s3Client) {\n\t\t\tthis.s3Client = this.configuration.s3Client;\n\t\t} else {\n\t\t\tconst clientConfig: any = {\n\t\t\t\tregion: this.configuration.region,\n\t\t\t};\n\n\t\t\tif (this.configuration.credentials) {\n\t\t\t\tclientConfig.credentials = this.configuration.credentials;\n\t\t\t}\n\n\t\t\tif (this.configuration.endpoint) {\n\t\t\t\tclientConfig.endpoint = this.configuration.endpoint;\n\t\t\t\tclientConfig.forcePathStyle = this.configuration.forcePathStyle;\n\t\t\t}\n\n\t\t\tthis.s3Client = new S3Client(clientConfig);\n\t\t}\n\n\t\t// Test S3 connection by checking if bucket exists\n\t\ttry {\n\t\t\tconst command = new HeadObjectCommand({\n\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\tKey: \"test-connection\", // This will likely return 404, but that's fine\n\t\t\t});\n\n\t\t\tawait this.s3Client.send(command);\n\t\t} catch (error: any) {\n\t\t\t// 404 is expected for the test key, any other error indicates connection issues\n\t\t\tif (error.$metadata?.httpStatusCode !== 404) {\n\t\t\t\t// Don't show credential errors as connection failures in development\n\t\t\t\tif (error.message?.includes(\"Could not load credentials\")) {\n\t\t\t\t\tconsole.warn(` ${kleur.yellow(\"S3 warning:\")} ${error.message}`);\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t` ${kleur.yellow(\"Note:\")} Ensure AWS credentials are properly configured for production use`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t` ${kleur.red(\"S3 connection failed:\")} ${error.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync onListen() {\n\t\tconst endpoint =\n\t\t\tthis.configuration.endpoint ||\n\t\t\t`https://s3.${this.configuration.region}.amazonaws.com`;\n\t\tconsole.log(\n\t\t\t` ${kleur.green(\"S3 extension configured:\")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`,\n\t\t);\n\n\t\tif (this.configuration.prefix) {\n\t\t\tconsole.log(\n\t\t\t\t` ${kleur.blue(\"S3 key prefix:\")} ${this.configuration.prefix}`,\n\t\t\t);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,IAAa,KAAb,cAAwBA,wCAAS;CAwEhC,YAAY,eAAyC;AACpD,QAAM,EAAE,CAAC;uBAtEuB;GAChC,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,gBAAgB;GAChB,OAAO,OAAO,EAAE,mBAAmB;IAClC,MAAM,MAAM,KAAK,aAAa,aAAa;AAE3C,QAAI;KACH,MAAM,UAAU,IAAIC,oCAAiB;MACpC,QAAQ,KAAK,cAAc;MAC3B,KAAK;MACL,CAAC;KAEF,MAAM,WAAW,MAAM,KAAK,SAAU,KAAK,QAAQ;AAEnD,SAAI,SAAS,MAAM;MAElB,MAAM,SAAuB,EAAE;MAC/B,MAAM,SAAS,SAAS,KAAK,sBAAsB,CAAC,WAAW;AAE/D,aAAO,MAAM;OACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,WAAI,KAAM;AACV,cAAO,KAAK,MAAM;;MAInB,MAAM,cAAc,OAAO,QACzB,KAAK,UAAU,MAAM,MAAM,QAC5B,EACA;MACD,MAAM,SAAS,IAAI,WAAW,YAAY;MAC1C,IAAI,SAAS;AAEb,WAAK,MAAM,SAAS,QAAQ;AAC3B,cAAO,IAAI,OAAO,OAAO;AACzB,iBAAU,MAAM;;AAGjB,aAAO;;AAGR,YAAO;aACC,OAAY;AACpB,SACC,MAAM,SAAS,eACf,MAAM,WAAW,mBAAmB,IAGpC,QAAO;AAER,WAAM;;;GAGR,OAAO,OAAO,EAAE,cAAc,YAAY;IACzC,MAAM,MAAM,KAAK,aAAa,aAAa;IAE3C,MAAM,UAAU,IAAIC,oCAAiB;KACpC,QAAQ,KAAK,cAAc;KAC3B,KAAK;KACL,MAAM;KACN,aAAa;KACb,CAAC;AAEF,UAAM,KAAK,SAAU,KAAK,QAAQ;;GAEnC;AAKA,OAAK,gBAAgB;GACpB,GAAG,KAAK;GACR,GAAG;GACH;AAGD,MAAI,CAAC,KAAK,cAAc,OACvB,OAAM,IAAI,MAAM,6BAA6B;;CAI/C,AAAQ,aAAa,cAA8B;AAElD,SAAO,GADQ,KAAK,cAAc,UAAU,KACzB,aAAa;;CAGjC,MAAM,cAAc;AAEnB,MAAI,KAAK,cAAc,SACtB,MAAK,WAAW,KAAK,cAAc;OAC7B;GACN,MAAM,eAAoB,EACzB,QAAQ,KAAK,cAAc,QAC3B;AAED,OAAI,KAAK,cAAc,YACtB,cAAa,cAAc,KAAK,cAAc;AAG/C,OAAI,KAAK,cAAc,UAAU;AAChC,iBAAa,WAAW,KAAK,cAAc;AAC3C,iBAAa,iBAAiB,KAAK,cAAc;;AAGlD,QAAK,WAAW,IAAIC,4BAAS,aAAa;;AAI3C,MAAI;GACH,MAAM,UAAU,IAAIC,qCAAkB;IACrC,QAAQ,KAAK,cAAc;IAC3B,KAAK;IACL,CAAC;AAEF,SAAM,KAAK,SAAS,KAAK,QAAQ;WACzB,OAAY;AAEpB,OAAI,MAAM,WAAW,mBAAmB,IAEvC,KAAI,MAAM,SAAS,SAAS,6BAA6B,EAAE;AAC1D,YAAQ,KAAK,KAAK,cAAM,OAAO,cAAc,CAAC,GAAG,MAAM,UAAU;AACjE,YAAQ,KACP,KAAK,cAAM,OAAO,QAAQ,CAAC,oEAC3B;SAED,SAAQ,MACP,KAAK,cAAM,IAAI,wBAAwB,CAAC,GAAG,MAAM,UACjD;;;CAML,MAAM,WAAW;EAChB,MAAM,WACL,KAAK,cAAc,YACnB,cAAc,KAAK,cAAc,OAAO;AACzC,UAAQ,IACP,KAAK,cAAM,MAAM,2BAA2B,CAAC,UAAU,KAAK,cAAc,OAAO,aAAa,WAC9F;AAED,MAAI,KAAK,cAAc,OACtB,SAAQ,IACP,KAAK,cAAM,KAAK,iBAAiB,CAAC,GAAG,KAAK,cAAc,SACxD"}
@@ -1,129 +1,98 @@
1
- import { Database } from '@hocuspocus/extension-database';
2
- import { PutObjectCommand, GetObjectCommand, S3Client, HeadObjectCommand } from '@aws-sdk/client-s3';
3
- import kleur from 'kleur';
1
+ import { Database } from "@hocuspocus/extension-database";
2
+ import { GetObjectCommand, HeadObjectCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
3
+ import kleur from "kleur";
4
4
 
5
- class S3 extends Database {
6
- constructor(configuration) {
7
- super({});
8
- this.configuration = {
9
- region: "us-east-1",
10
- bucket: "",
11
- prefix: "hocuspocus-documents/",
12
- forcePathStyle: false,
13
- fetch: async ({ documentName }) => {
14
- var _a;
15
- const key = this.getObjectKey(documentName);
16
- try {
17
- const command = new GetObjectCommand({
18
- Bucket: this.configuration.bucket,
19
- Key: key,
20
- });
21
- const response = await this.s3Client.send(command);
22
- if (response.Body) {
23
- // Convert stream to Uint8Array
24
- const chunks = [];
25
- const reader = response.Body.transformToWebStream().getReader();
26
- while (true) {
27
- const { done, value } = await reader.read();
28
- if (done)
29
- break;
30
- chunks.push(value);
31
- }
32
- // Combine all chunks into a single Uint8Array
33
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
34
- const result = new Uint8Array(totalLength);
35
- let offset = 0;
36
- for (const chunk of chunks) {
37
- result.set(chunk, offset);
38
- offset += chunk.length;
39
- }
40
- return result;
41
- }
42
- return null;
43
- }
44
- catch (error) {
45
- if (error.name === "NoSuchKey" ||
46
- ((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404) {
47
- // Document doesn't exist yet, return null
48
- return null;
49
- }
50
- throw error;
51
- }
52
- },
53
- store: async ({ documentName, state }) => {
54
- const key = this.getObjectKey(documentName);
55
- const command = new PutObjectCommand({
56
- Bucket: this.configuration.bucket,
57
- Key: key,
58
- Body: state,
59
- ContentType: "application/octet-stream",
60
- });
61
- await this.s3Client.send(command);
62
- },
63
- };
64
- this.configuration = {
65
- ...this.configuration,
66
- ...configuration,
67
- };
68
- // Validate required configuration
69
- if (!this.configuration.bucket) {
70
- throw new Error("S3 bucket name is required");
71
- }
72
- }
73
- getObjectKey(documentName) {
74
- const prefix = this.configuration.prefix || "";
75
- return `${prefix}${documentName}.bin`;
76
- }
77
- async onConfigure() {
78
- var _a, _b;
79
- // Use custom S3 client if provided, otherwise create one
80
- if (this.configuration.s3Client) {
81
- this.s3Client = this.configuration.s3Client;
82
- }
83
- else {
84
- const clientConfig = {
85
- region: this.configuration.region,
86
- };
87
- if (this.configuration.credentials) {
88
- clientConfig.credentials = this.configuration.credentials;
89
- }
90
- if (this.configuration.endpoint) {
91
- clientConfig.endpoint = this.configuration.endpoint;
92
- clientConfig.forcePathStyle = this.configuration.forcePathStyle;
93
- }
94
- this.s3Client = new S3Client(clientConfig);
95
- }
96
- // Test S3 connection by checking if bucket exists
97
- try {
98
- const command = new HeadObjectCommand({
99
- Bucket: this.configuration.bucket,
100
- Key: "test-connection", // This will likely return 404, but that's fine
101
- });
102
- await this.s3Client.send(command);
103
- }
104
- catch (error) {
105
- // 404 is expected for the test key, any other error indicates connection issues
106
- if (((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== 404) {
107
- // Don't show credential errors as connection failures in development
108
- if ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes("Could not load credentials")) {
109
- console.warn(` ${kleur.yellow("S3 warning:")} ${error.message}`);
110
- console.warn(` ${kleur.yellow("Note:")} Ensure AWS credentials are properly configured for production use`);
111
- }
112
- else {
113
- console.error(` ${kleur.red("S3 connection failed:")} ${error.message}`);
114
- }
115
- }
116
- }
117
- }
118
- async onListen() {
119
- const endpoint = this.configuration.endpoint ||
120
- `https://s3.${this.configuration.region}.amazonaws.com`;
121
- console.log(` ${kleur.green("S3 extension configured:")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`);
122
- if (this.configuration.prefix) {
123
- console.log(` ${kleur.blue("S3 key prefix:")} ${this.configuration.prefix}`);
124
- }
125
- }
126
- }
5
+ //#region packages/extension-s3/src/S3.ts
6
+ var S3 = class extends Database {
7
+ constructor(configuration) {
8
+ super({});
9
+ this.configuration = {
10
+ region: "us-east-1",
11
+ bucket: "",
12
+ prefix: "hocuspocus-documents/",
13
+ forcePathStyle: false,
14
+ fetch: async ({ documentName }) => {
15
+ const key = this.getObjectKey(documentName);
16
+ try {
17
+ const command = new GetObjectCommand({
18
+ Bucket: this.configuration.bucket,
19
+ Key: key
20
+ });
21
+ const response = await this.s3Client.send(command);
22
+ if (response.Body) {
23
+ const chunks = [];
24
+ const reader = response.Body.transformToWebStream().getReader();
25
+ while (true) {
26
+ const { done, value } = await reader.read();
27
+ if (done) break;
28
+ chunks.push(value);
29
+ }
30
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
31
+ const result = new Uint8Array(totalLength);
32
+ let offset = 0;
33
+ for (const chunk of chunks) {
34
+ result.set(chunk, offset);
35
+ offset += chunk.length;
36
+ }
37
+ return result;
38
+ }
39
+ return null;
40
+ } catch (error) {
41
+ if (error.name === "NoSuchKey" || error.$metadata?.httpStatusCode === 404) return null;
42
+ throw error;
43
+ }
44
+ },
45
+ store: async ({ documentName, state }) => {
46
+ const key = this.getObjectKey(documentName);
47
+ const command = new PutObjectCommand({
48
+ Bucket: this.configuration.bucket,
49
+ Key: key,
50
+ Body: state,
51
+ ContentType: "application/octet-stream"
52
+ });
53
+ await this.s3Client.send(command);
54
+ }
55
+ };
56
+ this.configuration = {
57
+ ...this.configuration,
58
+ ...configuration
59
+ };
60
+ if (!this.configuration.bucket) throw new Error("S3 bucket name is required");
61
+ }
62
+ getObjectKey(documentName) {
63
+ return `${this.configuration.prefix || ""}${documentName}.bin`;
64
+ }
65
+ async onConfigure() {
66
+ if (this.configuration.s3Client) this.s3Client = this.configuration.s3Client;
67
+ else {
68
+ const clientConfig = { region: this.configuration.region };
69
+ if (this.configuration.credentials) clientConfig.credentials = this.configuration.credentials;
70
+ if (this.configuration.endpoint) {
71
+ clientConfig.endpoint = this.configuration.endpoint;
72
+ clientConfig.forcePathStyle = this.configuration.forcePathStyle;
73
+ }
74
+ this.s3Client = new S3Client(clientConfig);
75
+ }
76
+ try {
77
+ const command = new HeadObjectCommand({
78
+ Bucket: this.configuration.bucket,
79
+ Key: "test-connection"
80
+ });
81
+ await this.s3Client.send(command);
82
+ } catch (error) {
83
+ if (error.$metadata?.httpStatusCode !== 404) if (error.message?.includes("Could not load credentials")) {
84
+ console.warn(` ${kleur.yellow("S3 warning:")} ${error.message}`);
85
+ console.warn(` ${kleur.yellow("Note:")} Ensure AWS credentials are properly configured for production use`);
86
+ } else console.error(` ${kleur.red("S3 connection failed:")} ${error.message}`);
87
+ }
88
+ }
89
+ async onListen() {
90
+ const endpoint = this.configuration.endpoint || `https://s3.${this.configuration.region}.amazonaws.com`;
91
+ console.log(` ${kleur.green("S3 extension configured:")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`);
92
+ if (this.configuration.prefix) console.log(` ${kleur.blue("S3 key prefix:")} ${this.configuration.prefix}`);
93
+ }
94
+ };
127
95
 
96
+ //#endregion
128
97
  export { S3 };
129
- //# sourceMappingURL=hocuspocus-s3.esm.js.map
98
+ //# sourceMappingURL=hocuspocus-s3.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hocuspocus-s3.esm.js","sources":["../src/S3.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hocuspocus-s3.esm.js","names":[],"sources":["../src/S3.ts"],"sourcesContent":["import type { DatabaseConfiguration } from \"@hocuspocus/extension-database\";\nimport { Database } from \"@hocuspocus/extension-database\";\nimport {\n\tS3Client,\n\tGetObjectCommand,\n\tPutObjectCommand,\n\tHeadObjectCommand,\n} from \"@aws-sdk/client-s3\";\nimport kleur from \"kleur\";\n\nexport interface S3Configuration extends DatabaseConfiguration {\n\t/**\n\t * AWS S3 region\n\t */\n\tregion?: string;\n\t/**\n\t * S3 bucket name\n\t */\n\tbucket: string;\n\t/**\n\t * S3 key prefix for documents (optional)\n\t */\n\tprefix?: string;\n\t/**\n\t * AWS credentials\n\t */\n\tcredentials?: {\n\t\taccessKeyId: string;\n\t\tsecretAccessKey: string;\n\t};\n\t/**\n\t * S3 endpoint URL (for S3-compatible services like MinIO)\n\t */\n\tendpoint?: string;\n\t/**\n\t * Force path style URLs (required for MinIO)\n\t */\n\tforcePathStyle?: boolean;\n\t/**\n\t * Custom S3 client\n\t */\n\ts3Client?: S3Client;\n}\n\nexport class S3 extends Database {\n\tprivate s3Client?: S3Client;\n\n\tconfiguration: S3Configuration = {\n\t\tregion: \"us-east-1\",\n\t\tbucket: \"\",\n\t\tprefix: \"hocuspocus-documents/\",\n\t\tforcePathStyle: false,\n\t\tfetch: async ({ documentName }) => {\n\t\t\tconst key = this.getObjectKey(documentName);\n\n\t\t\ttry {\n\t\t\t\tconst command = new GetObjectCommand({\n\t\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\t\tKey: key,\n\t\t\t\t});\n\n\t\t\t\tconst response = await this.s3Client!.send(command);\n\n\t\t\t\tif (response.Body) {\n\t\t\t\t\t// Convert stream to Uint8Array\n\t\t\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\t\t\tconst reader = response.Body.transformToWebStream().getReader();\n\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) break;\n\t\t\t\t\t\tchunks.push(value);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Combine all chunks into a single Uint8Array\n\t\t\t\t\tconst totalLength = chunks.reduce(\n\t\t\t\t\t\t(acc, chunk) => acc + chunk.length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t\tconst result = new Uint8Array(totalLength);\n\t\t\t\t\tlet offset = 0;\n\n\t\t\t\t\tfor (const chunk of chunks) {\n\t\t\t\t\t\tresult.set(chunk, offset);\n\t\t\t\t\t\toffset += chunk.length;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t} catch (error: any) {\n\t\t\t\tif (\n\t\t\t\t\terror.name === \"NoSuchKey\" ||\n\t\t\t\t\terror.$metadata?.httpStatusCode === 404\n\t\t\t\t) {\n\t\t\t\t\t// Document doesn't exist yet, return null\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tstore: async ({ documentName, state }) => {\n\t\t\tconst key = this.getObjectKey(documentName);\n\n\t\t\tconst command = new PutObjectCommand({\n\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\tKey: key,\n\t\t\t\tBody: state,\n\t\t\t\tContentType: \"application/octet-stream\",\n\t\t\t});\n\n\t\t\tawait this.s3Client!.send(command);\n\t\t},\n\t};\n\n\tconstructor(configuration: Partial<S3Configuration>) {\n\t\tsuper({});\n\n\t\tthis.configuration = {\n\t\t\t...this.configuration,\n\t\t\t...configuration,\n\t\t};\n\n\t\t// Validate required configuration\n\t\tif (!this.configuration.bucket) {\n\t\t\tthrow new Error(\"S3 bucket name is required\");\n\t\t}\n\t}\n\n\tprivate getObjectKey(documentName: string): string {\n\t\tconst prefix = this.configuration.prefix || \"\";\n\t\treturn `${prefix}${documentName}.bin`;\n\t}\n\n\tasync onConfigure() {\n\t\t// Use custom S3 client if provided, otherwise create one\n\t\tif (this.configuration.s3Client) {\n\t\t\tthis.s3Client = this.configuration.s3Client;\n\t\t} else {\n\t\t\tconst clientConfig: any = {\n\t\t\t\tregion: this.configuration.region,\n\t\t\t};\n\n\t\t\tif (this.configuration.credentials) {\n\t\t\t\tclientConfig.credentials = this.configuration.credentials;\n\t\t\t}\n\n\t\t\tif (this.configuration.endpoint) {\n\t\t\t\tclientConfig.endpoint = this.configuration.endpoint;\n\t\t\t\tclientConfig.forcePathStyle = this.configuration.forcePathStyle;\n\t\t\t}\n\n\t\t\tthis.s3Client = new S3Client(clientConfig);\n\t\t}\n\n\t\t// Test S3 connection by checking if bucket exists\n\t\ttry {\n\t\t\tconst command = new HeadObjectCommand({\n\t\t\t\tBucket: this.configuration.bucket,\n\t\t\t\tKey: \"test-connection\", // This will likely return 404, but that's fine\n\t\t\t});\n\n\t\t\tawait this.s3Client.send(command);\n\t\t} catch (error: any) {\n\t\t\t// 404 is expected for the test key, any other error indicates connection issues\n\t\t\tif (error.$metadata?.httpStatusCode !== 404) {\n\t\t\t\t// Don't show credential errors as connection failures in development\n\t\t\t\tif (error.message?.includes(\"Could not load credentials\")) {\n\t\t\t\t\tconsole.warn(` ${kleur.yellow(\"S3 warning:\")} ${error.message}`);\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t` ${kleur.yellow(\"Note:\")} Ensure AWS credentials are properly configured for production use`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t` ${kleur.red(\"S3 connection failed:\")} ${error.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync onListen() {\n\t\tconst endpoint =\n\t\t\tthis.configuration.endpoint ||\n\t\t\t`https://s3.${this.configuration.region}.amazonaws.com`;\n\t\tconsole.log(\n\t\t\t` ${kleur.green(\"S3 extension configured:\")} bucket=${this.configuration.bucket}, endpoint=${endpoint}`,\n\t\t);\n\n\t\tif (this.configuration.prefix) {\n\t\t\tconsole.log(\n\t\t\t\t` ${kleur.blue(\"S3 key prefix:\")} ${this.configuration.prefix}`,\n\t\t\t);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;AA4CA,IAAa,KAAb,cAAwB,SAAS;CAwEhC,YAAY,eAAyC;AACpD,QAAM,EAAE,CAAC;uBAtEuB;GAChC,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,gBAAgB;GAChB,OAAO,OAAO,EAAE,mBAAmB;IAClC,MAAM,MAAM,KAAK,aAAa,aAAa;AAE3C,QAAI;KACH,MAAM,UAAU,IAAI,iBAAiB;MACpC,QAAQ,KAAK,cAAc;MAC3B,KAAK;MACL,CAAC;KAEF,MAAM,WAAW,MAAM,KAAK,SAAU,KAAK,QAAQ;AAEnD,SAAI,SAAS,MAAM;MAElB,MAAM,SAAuB,EAAE;MAC/B,MAAM,SAAS,SAAS,KAAK,sBAAsB,CAAC,WAAW;AAE/D,aAAO,MAAM;OACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,WAAI,KAAM;AACV,cAAO,KAAK,MAAM;;MAInB,MAAM,cAAc,OAAO,QACzB,KAAK,UAAU,MAAM,MAAM,QAC5B,EACA;MACD,MAAM,SAAS,IAAI,WAAW,YAAY;MAC1C,IAAI,SAAS;AAEb,WAAK,MAAM,SAAS,QAAQ;AAC3B,cAAO,IAAI,OAAO,OAAO;AACzB,iBAAU,MAAM;;AAGjB,aAAO;;AAGR,YAAO;aACC,OAAY;AACpB,SACC,MAAM,SAAS,eACf,MAAM,WAAW,mBAAmB,IAGpC,QAAO;AAER,WAAM;;;GAGR,OAAO,OAAO,EAAE,cAAc,YAAY;IACzC,MAAM,MAAM,KAAK,aAAa,aAAa;IAE3C,MAAM,UAAU,IAAI,iBAAiB;KACpC,QAAQ,KAAK,cAAc;KAC3B,KAAK;KACL,MAAM;KACN,aAAa;KACb,CAAC;AAEF,UAAM,KAAK,SAAU,KAAK,QAAQ;;GAEnC;AAKA,OAAK,gBAAgB;GACpB,GAAG,KAAK;GACR,GAAG;GACH;AAGD,MAAI,CAAC,KAAK,cAAc,OACvB,OAAM,IAAI,MAAM,6BAA6B;;CAI/C,AAAQ,aAAa,cAA8B;AAElD,SAAO,GADQ,KAAK,cAAc,UAAU,KACzB,aAAa;;CAGjC,MAAM,cAAc;AAEnB,MAAI,KAAK,cAAc,SACtB,MAAK,WAAW,KAAK,cAAc;OAC7B;GACN,MAAM,eAAoB,EACzB,QAAQ,KAAK,cAAc,QAC3B;AAED,OAAI,KAAK,cAAc,YACtB,cAAa,cAAc,KAAK,cAAc;AAG/C,OAAI,KAAK,cAAc,UAAU;AAChC,iBAAa,WAAW,KAAK,cAAc;AAC3C,iBAAa,iBAAiB,KAAK,cAAc;;AAGlD,QAAK,WAAW,IAAI,SAAS,aAAa;;AAI3C,MAAI;GACH,MAAM,UAAU,IAAI,kBAAkB;IACrC,QAAQ,KAAK,cAAc;IAC3B,KAAK;IACL,CAAC;AAEF,SAAM,KAAK,SAAS,KAAK,QAAQ;WACzB,OAAY;AAEpB,OAAI,MAAM,WAAW,mBAAmB,IAEvC,KAAI,MAAM,SAAS,SAAS,6BAA6B,EAAE;AAC1D,YAAQ,KAAK,KAAK,MAAM,OAAO,cAAc,CAAC,GAAG,MAAM,UAAU;AACjE,YAAQ,KACP,KAAK,MAAM,OAAO,QAAQ,CAAC,oEAC3B;SAED,SAAQ,MACP,KAAK,MAAM,IAAI,wBAAwB,CAAC,GAAG,MAAM,UACjD;;;CAML,MAAM,WAAW;EAChB,MAAM,WACL,KAAK,cAAc,YACnB,cAAc,KAAK,cAAc,OAAO;AACzC,UAAQ,IACP,KAAK,MAAM,MAAM,2BAA2B,CAAC,UAAU,KAAK,cAAc,OAAO,aAAa,WAC9F;AAED,MAAI,KAAK,cAAc,OACtB,SAAQ,IACP,KAAK,MAAM,KAAK,iBAAiB,CAAC,GAAG,KAAK,cAAc,SACxD"}
@@ -0,0 +1,47 @@
1
+ import { Database, DatabaseConfiguration } from "@hocuspocus/extension-database";
2
+ import { S3Client } from "@aws-sdk/client-s3";
3
+
4
+ //#region packages/extension-s3/src/S3.d.ts
5
+ interface S3Configuration extends DatabaseConfiguration {
6
+ /**
7
+ * AWS S3 region
8
+ */
9
+ region?: string;
10
+ /**
11
+ * S3 bucket name
12
+ */
13
+ bucket: string;
14
+ /**
15
+ * S3 key prefix for documents (optional)
16
+ */
17
+ prefix?: string;
18
+ /**
19
+ * AWS credentials
20
+ */
21
+ credentials?: {
22
+ accessKeyId: string;
23
+ secretAccessKey: string;
24
+ };
25
+ /**
26
+ * S3 endpoint URL (for S3-compatible services like MinIO)
27
+ */
28
+ endpoint?: string;
29
+ /**
30
+ * Force path style URLs (required for MinIO)
31
+ */
32
+ forcePathStyle?: boolean;
33
+ /**
34
+ * Custom S3 client
35
+ */
36
+ s3Client?: S3Client;
37
+ }
38
+ declare class S3 extends Database {
39
+ private s3Client?;
40
+ configuration: S3Configuration;
41
+ constructor(configuration: Partial<S3Configuration>);
42
+ private getObjectKey;
43
+ onConfigure(): Promise<void>;
44
+ onListen(): Promise<void>;
45
+ }
46
+ //#endregion
47
+ export { S3, S3Configuration };