mbkbucket 3.3.0 → 3.3.1
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/index.js +7 -7
- package/{cli.js → lib/cli.js} +0 -1
- package/{src → lib/src}/config/index.js +1 -1
- package/package.json +13 -3
- package/.github/PACKAGE.md +0 -19
- package/.github/workflows/publish.yml +0 -88
- package/index.d.ts +0 -444
- package/lib/index.js +0 -17
- package/test/config-validation.test.js +0 -116
- /package/{public → lib/public}/bucketadmin.css +0 -0
- /package/{public → lib/public}/bucketadmin.js +0 -0
- /package/{public → lib/public}/mbkbucket-helper-demo.html +0 -0
- /package/{public → lib/public}/mbkbucket-helper.css +0 -0
- /package/{public → lib/public}/mbkbucket-helper.js +0 -0
- /package/{src → lib/src}/app.js +0 -0
- /package/{src → lib/src}/cli/auth-helper.js +0 -0
- /package/{src → lib/src}/config/validation.js +0 -0
- /package/{src → lib/src}/controllers/api.controller.js +0 -0
- /package/{src → lib/src}/controllers/dashboard.controller.js +0 -0
- /package/{src → lib/src}/controllers/info.controller.js +0 -0
- /package/{src → lib/src}/controllers/view.controller.js +0 -0
- /package/{src → lib/src}/middleware/async-handler.js +0 -0
- /package/{src → lib/src}/middleware/bucket-resolver.js +0 -0
- /package/{src → lib/src}/middleware/error-handler.js +0 -0
- /package/{src → lib/src}/middleware/rate-limiter.js +0 -0
- /package/{src → lib/src}/middleware/security.js +0 -0
- /package/{src → lib/src}/routes/api.routes.js +0 -0
- /package/{src → lib/src}/routes/index.js +0 -0
- /package/{src → lib/src}/routes/info.routes.js +0 -0
- /package/{src → lib/src}/routes/view.routes.js +0 -0
- /package/{src → lib/src}/services/s3.service.js +0 -0
- /package/{src → lib/src}/utils/errors.js +0 -0
- /package/{src → lib/src}/utils/helpers.js +0 -0
- /package/{src → lib/src}/utils/logger.js +0 -0
- /package/{views → lib/views}/bucket.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_alerts.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_delete_modal.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_filelist_skeleton.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_newfolder_modal.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_preview_modal.handlebars +0 -0
- /package/{views → lib/views}/bucketadmin_upload_modal.handlebars +0 -0
- /package/{views → lib/views}/bucketadmincontent.handlebars +0 -0
- /package/{views → lib/views}/bucketportal.handlebars +0 -0
- /package/{views → lib/views}/mbkbucket_info.handlebars +0 -0
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import dotenv from "dotenv";
|
|
2
|
-
import { createApp } from "./src/app.js";
|
|
3
|
-
import { checkVersion } from "./src/config/index.js";
|
|
4
|
-
import { runHealthCheck } from "./src/services/s3.service.js";
|
|
5
|
-
import { createLogger } from "./src/utils/logger.js";
|
|
2
|
+
import { createApp } from "./lib/src/app.js";
|
|
3
|
+
import { checkVersion } from "./lib/src/config/index.js";
|
|
4
|
+
import { runHealthCheck } from "./lib/src/services/s3.service.js";
|
|
5
|
+
import { createLogger } from "./lib/src/utils/logger.js";
|
|
6
6
|
|
|
7
7
|
dotenv.config();
|
|
8
8
|
|
|
@@ -26,9 +26,9 @@ if (isDevMode) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Re-export the public API for consumers of this package (named exports only)
|
|
29
|
-
export * from "./src/services/s3.service.js";
|
|
30
|
-
export * from "./src/config/index.js";
|
|
31
|
-
export { default as bucket } from "./src/routes/index.js";
|
|
29
|
+
export * from "./lib/src/services/s3.service.js";
|
|
30
|
+
export * from "./lib/src/config/index.js";
|
|
31
|
+
export { default as bucket } from "./lib/src/routes/index.js";
|
|
32
32
|
|
|
33
33
|
// Default export: the Express application instance
|
|
34
34
|
export default server;
|
package/{cli.js → lib/cli.js}
RENAMED
|
@@ -14,7 +14,7 @@ try {
|
|
|
14
14
|
packageJson = require("mbkbucket/package.json");
|
|
15
15
|
} catch {
|
|
16
16
|
// Fallback to relative path (for development/testing)
|
|
17
|
-
packageJson = require("
|
|
17
|
+
packageJson = require("../../../package.json");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// Parent project version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mbkbucket",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "Flexible S3/R2 bucket management — library, Express router, and CLI for mbktech.org applications. Provides upload, download, listing, multipart utilities, signed URLs, and a command-line interface with built-in configuration validation and health checks",
|
|
5
5
|
"author": "Muhammad Bin Khalid",
|
|
6
6
|
"homepage": "https://github.com/MIbnEKhalid/mbkbucket#readme",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"type": "module",
|
|
10
10
|
"types": "index.d.ts",
|
|
11
11
|
"bin": {
|
|
12
|
-
"mbkbucket": "./cli.js"
|
|
12
|
+
"mbkbucket": "./lib/cli.js"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"dev": "cross-env NODE_ENV=dev nodemon index.js",
|
|
@@ -44,6 +44,16 @@
|
|
|
44
44
|
"bugs": {
|
|
45
45
|
"url": "https://github.com/MIbnEKhalid/mbkbucket/issues"
|
|
46
46
|
},
|
|
47
|
+
"files": [
|
|
48
|
+
"lib",
|
|
49
|
+
".env.example",
|
|
50
|
+
".mbkbucket.config.example.json",
|
|
51
|
+
"cli.js",
|
|
52
|
+
"index.js",
|
|
53
|
+
"LICENSE",
|
|
54
|
+
"package.json",
|
|
55
|
+
"README.md"
|
|
56
|
+
],
|
|
47
57
|
"keywords": [
|
|
48
58
|
"mbkbucket",
|
|
49
59
|
"s3-bucket",
|
|
@@ -62,4 +72,4 @@
|
|
|
62
72
|
"file-upload",
|
|
63
73
|
"file-download"
|
|
64
74
|
]
|
|
65
|
-
}
|
|
75
|
+
}
|
package/.github/PACKAGE.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Package Information
|
|
2
|
-
|
|
3
|
-
This package is published on npm: [mbkbucket](https://www.npmjs.com/package/mbkbucket)
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install mbkbucket
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## What's Included
|
|
12
|
-
|
|
13
|
-
- **Library** — Full S3/R2 bucket management API (upload, download, list, delete, multipart, signed URLs)
|
|
14
|
-
- **Express Router** — Ready-to-use admin dashboard with Handlebars templates
|
|
15
|
-
- **CLI** — Command-line interface for managing buckets from the terminal ⚠️ *under development*
|
|
16
|
-
|
|
17
|
-
## Registry
|
|
18
|
-
|
|
19
|
-
Published to: npm Registry (https://registry.npmjs.org/)
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
name: Publish to npm and GitHub Packages
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- main
|
|
6
|
-
- master
|
|
7
|
-
|
|
8
|
-
permissions:
|
|
9
|
-
contents: read
|
|
10
|
-
packages: write
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
publish:
|
|
14
|
-
runs-on: ubuntu-latest
|
|
15
|
-
permissions:
|
|
16
|
-
contents: read
|
|
17
|
-
packages: write
|
|
18
|
-
steps:
|
|
19
|
-
- name: Checkout code
|
|
20
|
-
uses: actions/checkout@v3
|
|
21
|
-
|
|
22
|
-
- name: Setup Node.js for npm
|
|
23
|
-
uses: actions/setup-node@v3
|
|
24
|
-
with:
|
|
25
|
-
node-version: '18'
|
|
26
|
-
registry-url: 'https://registry.npmjs.org'
|
|
27
|
-
|
|
28
|
-
- name: Cache Node.js modules
|
|
29
|
-
uses: actions/cache@v3
|
|
30
|
-
with:
|
|
31
|
-
path: ~/.npm
|
|
32
|
-
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
33
|
-
restore-keys: |
|
|
34
|
-
${{ runner.os }}-node-
|
|
35
|
-
|
|
36
|
-
- name: Install dependencies
|
|
37
|
-
run: |
|
|
38
|
-
for i in {1..3}; do npm install && break || sleep 10; done
|
|
39
|
-
|
|
40
|
-
- name: Check if version exists on npm
|
|
41
|
-
id: check_version
|
|
42
|
-
run: |
|
|
43
|
-
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
44
|
-
VERSION=$(node -p "require('./package.json').version")
|
|
45
|
-
if npm view $PACKAGE_NAME@$VERSION version 2>/dev/null; then
|
|
46
|
-
echo "exists=true" >> $GITHUB_OUTPUT
|
|
47
|
-
echo "Version $VERSION already exists on npm"
|
|
48
|
-
else
|
|
49
|
-
echo "exists=false" >> $GITHUB_OUTPUT
|
|
50
|
-
echo "Version $VERSION does not exist, will publish"
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
- name: Publish to npm
|
|
54
|
-
if: steps.check_version.outputs.exists == 'false'
|
|
55
|
-
run: npm publish
|
|
56
|
-
env:
|
|
57
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
58
|
-
|
|
59
|
-
- name: Check if version exists on GitHub Packages
|
|
60
|
-
id: check_github_version
|
|
61
|
-
run: |
|
|
62
|
-
VERSION=$(node -p "require('./package.json').version")
|
|
63
|
-
if curl -f -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
|
64
|
-
https://npm.pkg.github.com/@mibnekhalid/mbkbucket/$VERSION 2>/dev/null; then
|
|
65
|
-
echo "exists=true" >> $GITHUB_OUTPUT
|
|
66
|
-
echo "Version $VERSION already exists on GitHub Packages"
|
|
67
|
-
else
|
|
68
|
-
echo "exists=false" >> $GITHUB_OUTPUT
|
|
69
|
-
echo "Version $VERSION does not exist on GitHub Packages, will publish"
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
- name: Modify package.json for GitHub Packages
|
|
73
|
-
if: steps.check_github_version.outputs.exists == 'false'
|
|
74
|
-
run: |
|
|
75
|
-
node -e "const pkg = require('./package.json'); pkg.name = '@mibnekhalid/mbkbucket'; pkg.publishConfig = { registry: 'https://npm.pkg.github.com' }; require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));"
|
|
76
|
-
|
|
77
|
-
- name: Setup Node.js for GitHub Packages
|
|
78
|
-
if: steps.check_github_version.outputs.exists == 'false'
|
|
79
|
-
uses: actions/setup-node@v3
|
|
80
|
-
with:
|
|
81
|
-
node-version: '18'
|
|
82
|
-
registry-url: 'https://npm.pkg.github.com'
|
|
83
|
-
|
|
84
|
-
- name: Publish to GitHub Packages
|
|
85
|
-
if: steps.check_github_version.outputs.exists == 'false'
|
|
86
|
-
run: npm publish
|
|
87
|
-
env:
|
|
88
|
-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/index.d.ts
DELETED
|
@@ -1,444 +0,0 @@
|
|
|
1
|
-
// Type definitions for mbkbucket
|
|
2
|
-
// Project: https://github.com/MIbnEKhalid/mbkbucket
|
|
3
|
-
|
|
4
|
-
import { Readable } from "stream";
|
|
5
|
-
import { Router, Application } from "express";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Shared types used across the package
|
|
9
|
-
*/
|
|
10
|
-
export interface BucketConfig {
|
|
11
|
-
BUCKET_NAME: string;
|
|
12
|
-
ENDPOINT?: string;
|
|
13
|
-
ACCESS_KEY_ID?: string;
|
|
14
|
-
SECRET_ACCESS_KEY?: string;
|
|
15
|
-
region?: string;
|
|
16
|
-
[key: string]: any;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type BucketConnectionMap = Record<string, BucketConfig>;
|
|
20
|
-
|
|
21
|
-
export interface S3ObjectResult {
|
|
22
|
-
Body: Readable;
|
|
23
|
-
ContentLength?: number;
|
|
24
|
-
ContentType?: string;
|
|
25
|
-
LastModified?: Date;
|
|
26
|
-
Key?: string;
|
|
27
|
-
[key: string]: any;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface UploadOptions {
|
|
31
|
-
metadata?: Record<string, string>;
|
|
32
|
-
cacheControl?: string;
|
|
33
|
-
storageClass?: string;
|
|
34
|
-
serverSideEncryption?: string;
|
|
35
|
-
bucketName?: string;
|
|
36
|
-
preventOverwrite?: boolean;
|
|
37
|
-
[key: string]: any;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface ListFilesOptions {
|
|
41
|
-
maxKeys?: number;
|
|
42
|
-
continuationToken?: string | null;
|
|
43
|
-
delimiter?: string | null;
|
|
44
|
-
fetchOwner?: boolean;
|
|
45
|
-
startAfter?: string | null;
|
|
46
|
-
bucketName?: string;
|
|
47
|
-
[key: string]: any;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface ListFilesResult extends Record<string, any> {
|
|
51
|
-
requestedAt: string;
|
|
52
|
-
totalFiles: number;
|
|
53
|
-
hasMore: boolean;
|
|
54
|
-
nextToken: string | null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface IncompleteMultipartUpload {
|
|
58
|
-
Key?: string;
|
|
59
|
-
UploadId?: string;
|
|
60
|
-
Initiated?: string;
|
|
61
|
-
Initiator?: { DisplayName?: string; [key: string]: any };
|
|
62
|
-
[key: string]: any;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface CleanupResult {
|
|
66
|
-
abortedCount: number;
|
|
67
|
-
uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
|
|
68
|
-
cleanedAt?: string;
|
|
69
|
-
[key: string]: any;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface ConfigVars {
|
|
73
|
-
publiView_enabled: boolean;
|
|
74
|
-
p_view_inline: boolean;
|
|
75
|
-
[key: string]: any;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* S3 exports (re-exported from lib/s3.js at package root)
|
|
80
|
-
*/
|
|
81
|
-
export function getAvailableBucketNames(): string[];
|
|
82
|
-
export function resolveBucketName(bucketName?: string | null): string;
|
|
83
|
-
export function getBucketConfig(bucketName?: string): BucketConfig;
|
|
84
|
-
export const bucketClient: any;
|
|
85
|
-
export function getAppName(): string;
|
|
86
|
-
export function ensureKeyHasAppPrefix(key?: string): string;
|
|
87
|
-
export function ensurePrefix(prefix?: string): string;
|
|
88
|
-
export function getBucketClient(bucketName?: string): any;
|
|
89
|
-
export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string; }>;
|
|
90
|
-
|
|
91
|
-
export function uploadFile(
|
|
92
|
-
key: string,
|
|
93
|
-
fileBuffer: Buffer | Uint8Array,
|
|
94
|
-
contentType: string,
|
|
95
|
-
options?: UploadOptions
|
|
96
|
-
): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string; } & Record<string, any>>;
|
|
97
|
-
|
|
98
|
-
export function downloadFile(
|
|
99
|
-
key: string,
|
|
100
|
-
options?: {
|
|
101
|
-
range?: string | null;
|
|
102
|
-
ifNoneMatch?: string | null;
|
|
103
|
-
ifModifiedSince?: Date | string | null;
|
|
104
|
-
responseCacheControl?: string | null;
|
|
105
|
-
responseContentType?: string | null;
|
|
106
|
-
bucketName?: string;
|
|
107
|
-
[key: string]: any;
|
|
108
|
-
}
|
|
109
|
-
): Promise<S3ObjectResult>;
|
|
110
|
-
|
|
111
|
-
export function deleteFile(key: string, bucketName?: string): Promise<{ key: string; deletedAt?: string } & Record<string, any>>;
|
|
112
|
-
|
|
113
|
-
export function deleteFiles(keys: string[], bucketName?: string): Promise<{
|
|
114
|
-
results: any[];
|
|
115
|
-
deletedCount: number;
|
|
116
|
-
errors: any[];
|
|
117
|
-
deletedAt: string;
|
|
118
|
-
}>;
|
|
119
|
-
|
|
120
|
-
export function deleteFolder(prefix: string, bucketName?: string): Promise<{
|
|
121
|
-
results?: any[];
|
|
122
|
-
deletedCount: number;
|
|
123
|
-
errors?: any[];
|
|
124
|
-
deletedAt: string;
|
|
125
|
-
prefix?: string;
|
|
126
|
-
}>;
|
|
127
|
-
|
|
128
|
-
export function listfiles(prefix?: string, options?: ListFilesOptions): Promise<ListFilesResult>;
|
|
129
|
-
|
|
130
|
-
export function getFileMetadata(key: string, bucketName?: string): Promise<{
|
|
131
|
-
key: string;
|
|
132
|
-
exists: boolean;
|
|
133
|
-
queriedAt: string;
|
|
134
|
-
ContentLength?: number;
|
|
135
|
-
ContentType?: string;
|
|
136
|
-
LastModified?: Date;
|
|
137
|
-
[key: string]: any;
|
|
138
|
-
}>;
|
|
139
|
-
|
|
140
|
-
export function fileExists(key: string, bucketName?: string): Promise<boolean>;
|
|
141
|
-
export function getFileSize(key: string, bucketName?: string): Promise<number | null>;
|
|
142
|
-
|
|
143
|
-
export function generateSignedUrl(
|
|
144
|
-
key: string,
|
|
145
|
-
operation?: "getObject" | "putObject" | string,
|
|
146
|
-
expiresIn?: number,
|
|
147
|
-
bucketName?: string
|
|
148
|
-
): Promise<{
|
|
149
|
-
url: string;
|
|
150
|
-
key: string;
|
|
151
|
-
operation: string;
|
|
152
|
-
expiresIn: number;
|
|
153
|
-
expiresAt: string;
|
|
154
|
-
generatedAt: string;
|
|
155
|
-
}>;
|
|
156
|
-
|
|
157
|
-
export function createMultipartUpload(
|
|
158
|
-
key: string,
|
|
159
|
-
contentType?: string,
|
|
160
|
-
metadata?: Record<string, string>,
|
|
161
|
-
bucketName?: string
|
|
162
|
-
): Promise<{ uploadId: string; key: string }>;
|
|
163
|
-
|
|
164
|
-
export function uploadPart(
|
|
165
|
-
key: string,
|
|
166
|
-
uploadId: string,
|
|
167
|
-
partNumber: number,
|
|
168
|
-
buffer: Buffer | Uint8Array,
|
|
169
|
-
bucketName?: string
|
|
170
|
-
): Promise<{ ETag: string; partNumber: number }>;
|
|
171
|
-
|
|
172
|
-
export function completeMultipartUpload(
|
|
173
|
-
key: string,
|
|
174
|
-
uploadId: string,
|
|
175
|
-
parts: Array<{ partNumber: number; ETag: string }>,
|
|
176
|
-
bucketName?: string
|
|
177
|
-
): Promise<{ key: string }>;
|
|
178
|
-
|
|
179
|
-
export function abortMultipartUpload(
|
|
180
|
-
key: string,
|
|
181
|
-
uploadId: string,
|
|
182
|
-
bucketName?: string
|
|
183
|
-
): Promise<{ key: string; abortedAt: string }>;
|
|
184
|
-
|
|
185
|
-
export function listIncompleteMultipartUploads(
|
|
186
|
-
prefix?: string,
|
|
187
|
-
bucketName?: string
|
|
188
|
-
): Promise<IncompleteMultipartUpload[]>;
|
|
189
|
-
|
|
190
|
-
export function cleanupIncompleteMultipartUploads(
|
|
191
|
-
olderThanDays?: number,
|
|
192
|
-
prefix?: string,
|
|
193
|
-
bucketName?: string
|
|
194
|
-
): Promise<CleanupResult>;
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Config exports (re-exported from lib/config/index.js at package root)
|
|
198
|
-
*/
|
|
199
|
-
export const packageJson: Record<string, any>;
|
|
200
|
-
export const appVersion: string;
|
|
201
|
-
export const mbkbucketVar: ConfigVars;
|
|
202
|
-
export function getLatestVersion(): Promise<string | null>;
|
|
203
|
-
export function checkVersion(): Promise<void>;
|
|
204
|
-
export function parseAndValidateMbkbucketVar(rawValue?: string): ConfigVars;
|
|
205
|
-
export function parseAndValidateBucketConnection(rawValue?: string): BucketConnectionMap | null;
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Router export (re-exported from lib/routes/index.js at package root as `bucket`)
|
|
209
|
-
*/
|
|
210
|
-
export const bucket: Router;
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Root default export from index.js: configured Express application
|
|
214
|
-
*/
|
|
215
|
-
declare const server: Application;
|
|
216
|
-
export default server;
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Subpath module declarations
|
|
220
|
-
*/
|
|
221
|
-
declare module "mbkbucket/lib/s3" {
|
|
222
|
-
import { Readable } from "stream";
|
|
223
|
-
|
|
224
|
-
export interface BucketConfig {
|
|
225
|
-
BUCKET_NAME: string;
|
|
226
|
-
ENDPOINT?: string;
|
|
227
|
-
ACCESS_KEY_ID?: string;
|
|
228
|
-
SECRET_ACCESS_KEY?: string;
|
|
229
|
-
region?: string;
|
|
230
|
-
[key: string]: any;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export type BucketConnectionMap = Record<string, BucketConfig>;
|
|
234
|
-
|
|
235
|
-
export interface S3ObjectResult {
|
|
236
|
-
Body: Readable;
|
|
237
|
-
ContentLength?: number;
|
|
238
|
-
ContentType?: string;
|
|
239
|
-
LastModified?: Date;
|
|
240
|
-
Key?: string;
|
|
241
|
-
[key: string]: any;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export interface UploadOptions {
|
|
245
|
-
metadata?: Record<string, string>;
|
|
246
|
-
cacheControl?: string;
|
|
247
|
-
storageClass?: string;
|
|
248
|
-
serverSideEncryption?: string;
|
|
249
|
-
bucketName?: string;
|
|
250
|
-
preventOverwrite?: boolean;
|
|
251
|
-
[key: string]: any;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export interface ListFilesOptions {
|
|
255
|
-
maxKeys?: number;
|
|
256
|
-
continuationToken?: string | null;
|
|
257
|
-
delimiter?: string | null;
|
|
258
|
-
fetchOwner?: boolean;
|
|
259
|
-
startAfter?: string | null;
|
|
260
|
-
bucketName?: string;
|
|
261
|
-
[key: string]: any;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export interface ListFilesResult extends Record<string, any> {
|
|
265
|
-
requestedAt: string;
|
|
266
|
-
totalFiles: number;
|
|
267
|
-
hasMore: boolean;
|
|
268
|
-
nextToken: string | null;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
export interface IncompleteMultipartUpload {
|
|
272
|
-
Key?: string;
|
|
273
|
-
UploadId?: string;
|
|
274
|
-
Initiated?: string;
|
|
275
|
-
Initiator?: { DisplayName?: string; [key: string]: any };
|
|
276
|
-
[key: string]: any;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export interface CleanupResult {
|
|
280
|
-
abortedCount: number;
|
|
281
|
-
uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
|
|
282
|
-
cleanedAt?: string;
|
|
283
|
-
[key: string]: any;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export function getAvailableBucketNames(): string[];
|
|
287
|
-
export function resolveBucketName(bucketName?: string | null): string;
|
|
288
|
-
export function getBucketConfig(bucketName?: string): BucketConfig;
|
|
289
|
-
export const bucketClient: any;
|
|
290
|
-
export function getAppName(): string;
|
|
291
|
-
export function ensureKeyHasAppPrefix(key?: string): string;
|
|
292
|
-
export function ensurePrefix(prefix?: string): string;
|
|
293
|
-
export function getBucketClient(bucketName?: string): any;
|
|
294
|
-
export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string; }>;
|
|
295
|
-
|
|
296
|
-
export function uploadFile(
|
|
297
|
-
key: string,
|
|
298
|
-
fileBuffer: Buffer | Uint8Array,
|
|
299
|
-
contentType: string,
|
|
300
|
-
options?: UploadOptions
|
|
301
|
-
): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string } & Record<string, any>>;
|
|
302
|
-
|
|
303
|
-
export function downloadFile(
|
|
304
|
-
key: string,
|
|
305
|
-
options?: {
|
|
306
|
-
range?: string | null;
|
|
307
|
-
ifNoneMatch?: string | null;
|
|
308
|
-
ifModifiedSince?: Date | string | null;
|
|
309
|
-
responseCacheControl?: string | null;
|
|
310
|
-
responseContentType?: string | null;
|
|
311
|
-
bucketName?: string;
|
|
312
|
-
[key: string]: any;
|
|
313
|
-
}
|
|
314
|
-
): Promise<S3ObjectResult>;
|
|
315
|
-
|
|
316
|
-
export function deleteFile(key: string, bucketName?: string): Promise<{ key: string; deletedAt?: string } & Record<string, any>>;
|
|
317
|
-
export function deleteFiles(keys: string[], bucketName?: string): Promise<{
|
|
318
|
-
results: any[];
|
|
319
|
-
deletedCount: number;
|
|
320
|
-
errors: any[];
|
|
321
|
-
deletedAt: string;
|
|
322
|
-
}>;
|
|
323
|
-
|
|
324
|
-
export function deleteFolder(prefix: string, bucketName?: string): Promise<{
|
|
325
|
-
results?: any[];
|
|
326
|
-
deletedCount: number;
|
|
327
|
-
errors?: any[];
|
|
328
|
-
deletedAt: string;
|
|
329
|
-
prefix?: string;
|
|
330
|
-
}>;
|
|
331
|
-
|
|
332
|
-
export function listfiles(prefix?: string, options?: ListFilesOptions): Promise<ListFilesResult>;
|
|
333
|
-
|
|
334
|
-
export function getFileMetadata(key: string, bucketName?: string): Promise<{
|
|
335
|
-
key: string;
|
|
336
|
-
exists: boolean;
|
|
337
|
-
queriedAt: string;
|
|
338
|
-
ContentLength?: number;
|
|
339
|
-
ContentType?: string;
|
|
340
|
-
LastModified?: Date;
|
|
341
|
-
[key: string]: any;
|
|
342
|
-
}>;
|
|
343
|
-
|
|
344
|
-
export function fileExists(key: string, bucketName?: string): Promise<boolean>;
|
|
345
|
-
export function getFileSize(key: string, bucketName?: string): Promise<number | null>;
|
|
346
|
-
|
|
347
|
-
export function generateSignedUrl(
|
|
348
|
-
key: string,
|
|
349
|
-
operation?: "getObject" | "putObject" | string,
|
|
350
|
-
expiresIn?: number,
|
|
351
|
-
bucketName?: string
|
|
352
|
-
): Promise<{
|
|
353
|
-
url: string;
|
|
354
|
-
key: string;
|
|
355
|
-
operation: string;
|
|
356
|
-
expiresIn: number;
|
|
357
|
-
expiresAt: string;
|
|
358
|
-
generatedAt: string;
|
|
359
|
-
}>;
|
|
360
|
-
|
|
361
|
-
export function createMultipartUpload(
|
|
362
|
-
key: string,
|
|
363
|
-
contentType?: string,
|
|
364
|
-
metadata?: Record<string, string>,
|
|
365
|
-
bucketName?: string
|
|
366
|
-
): Promise<{ uploadId: string; key: string }>;
|
|
367
|
-
|
|
368
|
-
export function uploadPart(
|
|
369
|
-
key: string,
|
|
370
|
-
uploadId: string,
|
|
371
|
-
partNumber: number,
|
|
372
|
-
buffer: Buffer | Uint8Array,
|
|
373
|
-
bucketName?: string
|
|
374
|
-
): Promise<{ ETag: string; partNumber: number }>;
|
|
375
|
-
|
|
376
|
-
export function completeMultipartUpload(
|
|
377
|
-
key: string,
|
|
378
|
-
uploadId: string,
|
|
379
|
-
parts: Array<{ partNumber: number; ETag: string }>,
|
|
380
|
-
bucketName?: string
|
|
381
|
-
): Promise<{ key: string }>;
|
|
382
|
-
|
|
383
|
-
export function abortMultipartUpload(
|
|
384
|
-
key: string,
|
|
385
|
-
uploadId: string,
|
|
386
|
-
bucketName?: string
|
|
387
|
-
): Promise<{ key: string; abortedAt: string }>;
|
|
388
|
-
|
|
389
|
-
export function listIncompleteMultipartUploads(
|
|
390
|
-
prefix?: string,
|
|
391
|
-
bucketName?: string
|
|
392
|
-
): Promise<IncompleteMultipartUpload[]>;
|
|
393
|
-
|
|
394
|
-
export function cleanupIncompleteMultipartUploads(
|
|
395
|
-
olderThanDays?: number,
|
|
396
|
-
prefix?: string,
|
|
397
|
-
bucketName?: string
|
|
398
|
-
): Promise<CleanupResult>;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
declare module "mbkbucket/lib/config/index" {
|
|
402
|
-
export interface ConfigVars {
|
|
403
|
-
publiView_enabled: boolean;
|
|
404
|
-
p_view_inline: boolean;
|
|
405
|
-
[key: string]: any;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
export interface BucketConfig {
|
|
409
|
-
BUCKET_NAME: string;
|
|
410
|
-
ENDPOINT?: string;
|
|
411
|
-
ACCESS_KEY_ID?: string;
|
|
412
|
-
SECRET_ACCESS_KEY?: string;
|
|
413
|
-
region?: string;
|
|
414
|
-
[key: string]: any;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
export type BucketConnectionMap = Record<string, BucketConfig>;
|
|
418
|
-
|
|
419
|
-
export const packageJson: Record<string, any>;
|
|
420
|
-
export const appVersion: string;
|
|
421
|
-
export const mbkbucketVar: ConfigVars;
|
|
422
|
-
export function getLatestVersion(): Promise<string | null>;
|
|
423
|
-
export function checkVersion(): Promise<void>;
|
|
424
|
-
export function parseAndValidateMbkbucketVar(rawValue?: string): ConfigVars;
|
|
425
|
-
export function parseAndValidateBucketConnection(rawValue?: string): BucketConnectionMap | null;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
declare module "mbkbucket/lib/config/validation" {
|
|
429
|
-
export function normalizeBooleanLike(value: any): any;
|
|
430
|
-
export function parseAndValidateMbkbucketVar(rawValue?: string): { [key: string]: any };
|
|
431
|
-
export function parseAndValidateBucketConnection(rawValue?: string): Record<string, any> | null;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
declare module "mbkbucket/lib/routes/index" {
|
|
435
|
-
import { Router } from "express";
|
|
436
|
-
const router: Router;
|
|
437
|
-
export default router;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
declare module "mbkbucket/lib/bucket" {
|
|
441
|
-
import { Router } from "express";
|
|
442
|
-
const router: Router;
|
|
443
|
-
export default router;
|
|
444
|
-
}
|
package/lib/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Barrel file: re-export all public items from the restructured src/ directory
|
|
2
|
-
export * from '../src/services/s3.service.js';
|
|
3
|
-
export * from '../src/config/index.js';
|
|
4
|
-
export { default as bucket } from '../src/routes/index.js';
|
|
5
|
-
|
|
6
|
-
import * as s3 from '../src/services/s3.service.js';
|
|
7
|
-
import * as config from '../src/config/index.js';
|
|
8
|
-
import bucket from '../src/routes/index.js';
|
|
9
|
-
|
|
10
|
-
// Default aggregate export for convenience
|
|
11
|
-
const defaultExport = {
|
|
12
|
-
...s3,
|
|
13
|
-
...config,
|
|
14
|
-
bucket,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export default defaultExport;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { parseAndValidateMbkbucketVar, parseAndValidateBucketConnection, normalizeBooleanLike } from '../src/config/validation.js';
|
|
4
|
-
|
|
5
|
-
test('parseAndValidateMbkbucketVar applies defaults when empty', () => {
|
|
6
|
-
const cfg = parseAndValidateMbkbucketVar(undefined);
|
|
7
|
-
assert.equal(cfg.p_view_inline, true);
|
|
8
|
-
assert.equal(cfg.publiView_enabled, false);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
test('parseAndValidateMbkbucketVar normalizes boolean-like strings', () => {
|
|
12
|
-
const cfg = parseAndValidateMbkbucketVar(JSON.stringify({
|
|
13
|
-
p_view_inline: 'false',
|
|
14
|
-
publiView_enabled: 'true'
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
assert.equal(cfg.p_view_inline, false);
|
|
18
|
-
assert.equal(cfg.publiView_enabled, true);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('parseAndValidateMbkbucketVar rejects invalid JSON', () => {
|
|
22
|
-
assert.throws(() => parseAndValidateMbkbucketVar('{oops'), /Invalid JSON/);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('parseAndValidateMbkbucketVar rejects invalid boolean values', () => {
|
|
26
|
-
assert.throws(() => parseAndValidateMbkbucketVar(JSON.stringify({
|
|
27
|
-
p_view_inline: 'not-bool'
|
|
28
|
-
})), /must be a boolean/);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('parseAndValidateMbkbucketVar accepts common boolean aliases', () => {
|
|
32
|
-
const cfg = parseAndValidateMbkbucketVar(JSON.stringify({
|
|
33
|
-
p_view_inline: ' ON ',
|
|
34
|
-
publiView_enabled: '0'
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
assert.equal(cfg.p_view_inline, true);
|
|
38
|
-
assert.equal(cfg.publiView_enabled, false);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('parseAndValidateMbkbucketVar rejects non-object values', () => {
|
|
42
|
-
assert.throws(() => parseAndValidateMbkbucketVar('null'), /must be a valid object/);
|
|
43
|
-
assert.throws(() => parseAndValidateMbkbucketVar('[]'), /must be a valid object/);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('normalizeBooleanLike returns untouched for unsupported values', () => {
|
|
47
|
-
assert.equal(normalizeBooleanLike('maybe'), 'maybe');
|
|
48
|
-
assert.equal(normalizeBooleanLike(123), 123);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('parseAndValidateBucketConnection accepts multi-bucket config', () => {
|
|
52
|
-
const raw = JSON.stringify({
|
|
53
|
-
R2_Bucket: {
|
|
54
|
-
BUCKET_NAME: 'my-r2-bucket',
|
|
55
|
-
ACCESS_KEY_ID: 'abc',
|
|
56
|
-
SECRET_ACCESS_KEY: 'def',
|
|
57
|
-
ENDPOINT: 'https://example.r2.cloudflarestorage.com'
|
|
58
|
-
},
|
|
59
|
-
S3_Bucket: {
|
|
60
|
-
BUCKET_NAME: 'my-s3-bucket',
|
|
61
|
-
ACCESS_KEY_ID: 'ghi',
|
|
62
|
-
SECRET_ACCESS_KEY: 'jkl',
|
|
63
|
-
ENDPOINT: 'https://s3.ap-southeast-1.amazonaws.com'
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const cfg = parseAndValidateBucketConnection(raw);
|
|
68
|
-
assert.deepEqual(Object.keys(cfg), ['R2_Bucket', 'S3_Bucket']);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('parseAndValidateBucketConnection returns null when unset', () => {
|
|
72
|
-
assert.equal(parseAndValidateBucketConnection(undefined), null);
|
|
73
|
-
assert.equal(parseAndValidateBucketConnection(''), null);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('parseAndValidateBucketConnection rejects invalid JSON', () => {
|
|
77
|
-
assert.throws(() => parseAndValidateBucketConnection('{oops'), /not valid JSON/);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('parseAndValidateBucketConnection rejects empty object and array', () => {
|
|
81
|
-
assert.throws(() => parseAndValidateBucketConnection('{}'), /non-empty object/);
|
|
82
|
-
assert.throws(() => parseAndValidateBucketConnection('[]'), /non-empty object/);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('parseAndValidateBucketConnection rejects missing required fields', () => {
|
|
86
|
-
const raw = JSON.stringify({
|
|
87
|
-
bad: {
|
|
88
|
-
BUCKET_NAME: 'x',
|
|
89
|
-
ACCESS_KEY_ID: 'y',
|
|
90
|
-
ENDPOINT: 'https://example.com'
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
assert.throws(() => parseAndValidateBucketConnection(raw), /missing required fields/);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('parseAndValidateBucketConnection rejects quoted inner object shape', () => {
|
|
98
|
-
const raw = JSON.stringify({
|
|
99
|
-
bad: '{"BUCKET_NAME":"x"}'
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
assert.throws(() => parseAndValidateBucketConnection(raw), /must be an object/);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('parseAndValidateBucketConnection rejects empty required fields', () => {
|
|
106
|
-
const raw = JSON.stringify({
|
|
107
|
-
bad: {
|
|
108
|
-
BUCKET_NAME: '',
|
|
109
|
-
ACCESS_KEY_ID: 'abc',
|
|
110
|
-
SECRET_ACCESS_KEY: 'def',
|
|
111
|
-
ENDPOINT: 'https://example.com'
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
assert.throws(() => parseAndValidateBucketConnection(raw), /missing required fields/);
|
|
116
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{src → lib/src}/app.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|