@muhgholy/next-drive 4.10.1 → 4.12.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.
package/README.md
CHANGED
|
@@ -90,6 +90,9 @@ import "@muhgholy/next-drive/client/styles.css";
|
|
|
90
90
|
|
|
91
91
|
Create `lib/drive.ts` to configure storage, security, and authentication:
|
|
92
92
|
|
|
93
|
+
> [!IMPORTANT]
|
|
94
|
+
> You **must** connect to your database (e.g., Mongoose) **before** calling `driveConfiguration`. The configuration initialization will fail if the database connection is not ready.
|
|
95
|
+
|
|
93
96
|
```typescript
|
|
94
97
|
// lib/drive.ts
|
|
95
98
|
import { driveConfiguration } from "@muhgholy/next-drive/server";
|
|
@@ -540,6 +543,40 @@ cors: {
|
|
|
540
543
|
|
|
541
544
|
> When `credentials: true`, you must specify explicit origins (not `'*'`).
|
|
542
545
|
|
|
546
|
+
### Drive Modes
|
|
547
|
+
|
|
548
|
+
Next Drive supports two operation modes:
|
|
549
|
+
|
|
550
|
+
1. **NORMAL** (Default): Requires `information` callback to identify the user and set quota. Enforces security limits.
|
|
551
|
+
2. **ROOT**: System/Admin mode. No authentication required by default (unless you provide `information`).
|
|
552
|
+
|
|
553
|
+
> [!WARNING]
|
|
554
|
+
> In both modes, ensure your database connection is active before initializing the configuration.
|
|
555
|
+
|
|
556
|
+
**Root Mode Configuration:**
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
driveConfiguration({
|
|
560
|
+
mode: 'ROOT', // Enable root mode
|
|
561
|
+
database: 'MONGOOSE',
|
|
562
|
+
apiUrl: '/api/drive',
|
|
563
|
+
storage: { path: '/var/data/drive' },
|
|
564
|
+
// Optional: Security defaults to 10GB limit and all mime types if omitted
|
|
565
|
+
security: {
|
|
566
|
+
maxUploadSizeInBytes: 10 * 1024 * 1024 * 1024, // 10GB
|
|
567
|
+
allowedMimeTypes: ['*/*']
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**Key differences in ROOT mode:**
|
|
573
|
+
- `information` callback is **optional**.
|
|
574
|
+
- If `information` is omitted:
|
|
575
|
+
- `key` is `null` (files owned by system).
|
|
576
|
+
- `quota` is unlimited.
|
|
577
|
+
- Default `security.maxUploadSizeInBytes` is **10GB**.
|
|
578
|
+
- Default `security.allowedMimeTypes` is `['*/*']` (all files allowed).
|
|
579
|
+
|
|
543
580
|
---
|
|
544
581
|
|
|
545
582
|
## Google Drive Integration
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { TDriveFile } from '../types/client';
|
|
3
3
|
export declare const DriveFileChooser: (props: Readonly<{
|
|
4
|
-
value
|
|
4
|
+
value?: TDriveFile | TDriveFile[] | null;
|
|
5
5
|
onChange: (files: TDriveFile | TDriveFile[] | null) => void;
|
|
6
6
|
multiple?: boolean;
|
|
7
7
|
accept?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-chooser.d.ts","sourceRoot":"","sources":["../../src/client/file-chooser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAuWjD,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,CAAC;IAC7C,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"file-chooser.d.ts","sourceRoot":"","sources":["../../src/client/file-chooser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAuWjD,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,CAAC;IAC7C,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC,sBAgLD,CAAC"}
|
package/dist/client/index.cjs
CHANGED
|
@@ -3044,7 +3044,7 @@ var MobileSidebarSheet = () => {
|
|
|
3044
3044
|
};
|
|
3045
3045
|
var DriveFileChooser = (props) => {
|
|
3046
3046
|
const {
|
|
3047
|
-
value,
|
|
3047
|
+
value = null,
|
|
3048
3048
|
onChange,
|
|
3049
3049
|
multiple = false,
|
|
3050
3050
|
accept,
|
|
@@ -3109,10 +3109,10 @@ var DriveFileChooser = (props) => {
|
|
|
3109
3109
|
) : (
|
|
3110
3110
|
/* Selected Files Display */
|
|
3111
3111
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkTA6L5FYG_cjs.cn("nd:rounded-lg nd:border", error ? "nd:border-destructive" : "nd:border-border", disabled && "nd:opacity-50"), children: [
|
|
3112
|
-
!multiple && displayFiles[0] && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex nd:items-center nd:gap-3 nd:p-2.5", children: [
|
|
3113
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:size-12 nd:rounded-lg nd:overflow-hidden nd:bg-muted/30 nd:flex nd:items-center nd:justify-center nd:shrink-0", children: displayFiles[0].file.mime
|
|
3112
|
+
!multiple && displayFiles[0] && displayFiles[0].file && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex nd:items-center nd:gap-3 nd:p-2.5", children: [
|
|
3113
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:size-12 nd:rounded-lg nd:overflow-hidden nd:bg-muted/30 nd:flex nd:items-center nd:justify-center nd:shrink-0", children: displayFiles[0].file.mime?.startsWith("image/") ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: createUrl(displayFiles[0]), alt: displayFiles[0].file.name || "", className: "nd:size-full nd:object-cover" }) : chunkTA6L5FYG_cjs.getFileIcon(displayFiles[0].file.mime || "", false, "nd:size-6 nd:text-muted-foreground") }),
|
|
3114
3114
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex-1 nd:min-w-0", children: [
|
|
3115
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "nd:text-sm nd:font-medium nd:truncate", children: displayFiles[0].file.name }),
|
|
3115
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "nd:text-sm nd:font-medium nd:truncate", children: displayFiles[0].file.name || "Unknown" }),
|
|
3116
3116
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "nd:text-xs nd:text-muted-foreground", children: displayFiles[0].file.mime || "File" })
|
|
3117
3117
|
] }),
|
|
3118
3118
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex nd:items-center nd:gap-1 nd:shrink-0", children: [
|
|
@@ -3133,9 +3133,9 @@ var DriveFileChooser = (props) => {
|
|
|
3133
3133
|
!disabled && /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "nd:h-7 nd:text-xs nd:text-muted-foreground", onClick: () => onChange([]), children: "Clear" })
|
|
3134
3134
|
] })
|
|
3135
3135
|
] }),
|
|
3136
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:max-h-40 nd:overflow-y-auto nd:divide-y nd:divide-border/50", children: displayFiles.map((file) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex nd:items-center nd:gap-2.5 nd:px-3 nd:py-2 nd:hover:bg-muted/20", children: [
|
|
3137
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:size-8 nd:rounded nd:overflow-hidden nd:bg-muted/30 nd:flex nd:items-center nd:justify-center nd:shrink-0", children: file.file.mime
|
|
3138
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "nd:flex-1 nd:text-sm nd:truncate", children: file.file.name }),
|
|
3136
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:max-h-40 nd:overflow-y-auto nd:divide-y nd:divide-border/50", children: displayFiles.filter((file) => file?.file).map((file) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nd:flex nd:items-center nd:gap-2.5 nd:px-3 nd:py-2 nd:hover:bg-muted/20", children: [
|
|
3137
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "nd:size-8 nd:rounded nd:overflow-hidden nd:bg-muted/30 nd:flex nd:items-center nd:justify-center nd:shrink-0", children: file.file.mime?.startsWith("image/") ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: createUrl(file), alt: file.file.name || "", className: "nd:size-full nd:object-cover" }) : chunkTA6L5FYG_cjs.getFileIcon(file.file.mime || "", false, "nd:size-4 nd:text-muted-foreground") }),
|
|
3138
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "nd:flex-1 nd:text-sm nd:truncate", children: file.file.name || "Unknown" }),
|
|
3139
3139
|
!disabled && /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "nd:size-7 nd:shrink-0", onClick: () => handleRemove(file.id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "nd:size-3.5" }) })
|
|
3140
3140
|
] }, file.id)) })
|
|
3141
3141
|
] })
|