@vryzel/file-next 0.5.3 → 0.6.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/README.md +2 -1
- package/dist/{filesystem-Djiiu6YU.d.ts → filesystem-CF4TFF58.d.ts} +18 -122
- package/dist/{filesystem-C0vVDtg4.d.cts → filesystem-CFRC-gky.d.cts} +18 -122
- package/dist/index.cjs +52 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +52 -35
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +186 -78
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +34 -110
- package/dist/server/index.d.ts +34 -110
- package/dist/server/index.js +186 -78
- package/dist/server/index.js.map +1 -1
- package/dist/sync/index.cjs +33 -10
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +33 -10
- package/dist/sync/index.js.map +1 -1
- package/dist/{with-auth-OZNiZGga.d.ts → with-auth-BvFHyioA.d.ts} +1 -1
- package/dist/{with-auth-Dtn57B_S.d.cts → with-auth-UBz99KZJ.d.cts} +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ import { createShareRouteHandler } from "@vryzel/file-next/server";
|
|
|
169
169
|
export const GET = createShareRouteHandler({ store, fs });
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
The handler streams
|
|
172
|
+
The handler streams objects up to 32MB through Next.js and redirects larger ones to a 60-second signed URL. Folders cannot be shared this way. Optional `sharePathPrefix` on `createServerActions` (default `/api/share`).
|
|
173
173
|
|
|
174
174
|
### 8. Route handlers (upload / download)
|
|
175
175
|
|
|
@@ -180,6 +180,7 @@ import { getFileSystem } from "@vryzel/file-next";
|
|
|
180
180
|
|
|
181
181
|
export const PUT = createUploadRouteHandler({
|
|
182
182
|
fs: getFileSystem(),
|
|
183
|
+
getAuth: async () => session ?? null,
|
|
183
184
|
maxBytes: 25 * 1024 * 1024,
|
|
184
185
|
allowedContentTypes: ["image/*", "application/pdf"],
|
|
185
186
|
});
|
|
@@ -206,6 +206,11 @@ interface PresignedUploadInput {
|
|
|
206
206
|
contentType?: string;
|
|
207
207
|
/** Expiry in seconds. Providers enforce a max (e.g. 7 days for S3). */
|
|
208
208
|
expiresIn?: number;
|
|
209
|
+
/**
|
|
210
|
+
* When set, the signature binds `Content-Length` to this value.
|
|
211
|
+
* A PUT with any other length is rejected by the provider.
|
|
212
|
+
*/
|
|
213
|
+
contentLength?: number;
|
|
209
214
|
}
|
|
210
215
|
interface PresignedDownloadInput {
|
|
211
216
|
key: S3Key;
|
|
@@ -401,53 +406,19 @@ interface S3CompatibleAdapter {
|
|
|
401
406
|
declare const CredentialsSchema: z.ZodObject<{
|
|
402
407
|
accessKeyId: z.ZodString;
|
|
403
408
|
secretAccessKey: z.ZodString;
|
|
404
|
-
},
|
|
405
|
-
accessKeyId: string;
|
|
406
|
-
secretAccessKey: string;
|
|
407
|
-
}, {
|
|
408
|
-
accessKeyId: string;
|
|
409
|
-
secretAccessKey: string;
|
|
410
|
-
}>;
|
|
409
|
+
}, z.core.$strip>;
|
|
411
410
|
type Credentials = z.infer<typeof CredentialsSchema>;
|
|
412
411
|
declare const S3ConfigSchema: z.ZodObject<{
|
|
413
412
|
provider: z.ZodLiteral<"s3">;
|
|
414
413
|
bucket: z.ZodString;
|
|
415
414
|
region: z.ZodString;
|
|
416
|
-
/** Optional S3-compatible endpoint (MinIO, LocalStack, ...). */
|
|
417
415
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
418
416
|
credentials: z.ZodObject<{
|
|
419
417
|
accessKeyId: z.ZodString;
|
|
420
418
|
secretAccessKey: z.ZodString;
|
|
421
|
-
},
|
|
422
|
-
accessKeyId: string;
|
|
423
|
-
secretAccessKey: string;
|
|
424
|
-
}, {
|
|
425
|
-
accessKeyId: string;
|
|
426
|
-
secretAccessKey: string;
|
|
427
|
-
}>;
|
|
428
|
-
/** Default false; some S3-compatible providers need path-style. */
|
|
419
|
+
}, z.core.$strip>;
|
|
429
420
|
forcePathStyle: z.ZodDefault<z.ZodBoolean>;
|
|
430
|
-
},
|
|
431
|
-
provider: "s3";
|
|
432
|
-
bucket: string;
|
|
433
|
-
region: string;
|
|
434
|
-
credentials: {
|
|
435
|
-
accessKeyId: string;
|
|
436
|
-
secretAccessKey: string;
|
|
437
|
-
};
|
|
438
|
-
forcePathStyle: boolean;
|
|
439
|
-
endpoint?: string | undefined;
|
|
440
|
-
}, {
|
|
441
|
-
provider: "s3";
|
|
442
|
-
bucket: string;
|
|
443
|
-
region: string;
|
|
444
|
-
credentials: {
|
|
445
|
-
accessKeyId: string;
|
|
446
|
-
secretAccessKey: string;
|
|
447
|
-
};
|
|
448
|
-
endpoint?: string | undefined;
|
|
449
|
-
forcePathStyle?: boolean | undefined;
|
|
450
|
-
}>;
|
|
421
|
+
}, z.core.$strip>;
|
|
451
422
|
declare const R2ConfigSchema: z.ZodObject<{
|
|
452
423
|
provider: z.ZodLiteral<"r2">;
|
|
453
424
|
bucket: z.ZodString;
|
|
@@ -455,107 +426,29 @@ declare const R2ConfigSchema: z.ZodObject<{
|
|
|
455
426
|
credentials: z.ZodObject<{
|
|
456
427
|
accessKeyId: z.ZodString;
|
|
457
428
|
secretAccessKey: z.ZodString;
|
|
458
|
-
},
|
|
459
|
-
accessKeyId: string;
|
|
460
|
-
secretAccessKey: string;
|
|
461
|
-
}, {
|
|
462
|
-
accessKeyId: string;
|
|
463
|
-
secretAccessKey: string;
|
|
464
|
-
}>;
|
|
465
|
-
/** R2 ONLY supports path-style; the literal-true type makes that explicit. */
|
|
429
|
+
}, z.core.$strip>;
|
|
466
430
|
forcePathStyle: z.ZodLiteral<true>;
|
|
467
|
-
},
|
|
468
|
-
|
|
469
|
-
bucket: string;
|
|
470
|
-
endpoint: string;
|
|
471
|
-
credentials: {
|
|
472
|
-
accessKeyId: string;
|
|
473
|
-
secretAccessKey: string;
|
|
474
|
-
};
|
|
475
|
-
forcePathStyle: true;
|
|
476
|
-
}, {
|
|
477
|
-
provider: "r2";
|
|
478
|
-
bucket: string;
|
|
479
|
-
endpoint: string;
|
|
480
|
-
credentials: {
|
|
481
|
-
accessKeyId: string;
|
|
482
|
-
secretAccessKey: string;
|
|
483
|
-
};
|
|
484
|
-
forcePathStyle: true;
|
|
485
|
-
}>;
|
|
486
|
-
declare const FileSystemConfigSchema: z.ZodDiscriminatedUnion<"provider", [z.ZodObject<{
|
|
431
|
+
}, z.core.$strip>;
|
|
432
|
+
declare const FileSystemConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
487
433
|
provider: z.ZodLiteral<"s3">;
|
|
488
434
|
bucket: z.ZodString;
|
|
489
435
|
region: z.ZodString;
|
|
490
|
-
/** Optional S3-compatible endpoint (MinIO, LocalStack, ...). */
|
|
491
436
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
492
437
|
credentials: z.ZodObject<{
|
|
493
438
|
accessKeyId: z.ZodString;
|
|
494
439
|
secretAccessKey: z.ZodString;
|
|
495
|
-
},
|
|
496
|
-
accessKeyId: string;
|
|
497
|
-
secretAccessKey: string;
|
|
498
|
-
}, {
|
|
499
|
-
accessKeyId: string;
|
|
500
|
-
secretAccessKey: string;
|
|
501
|
-
}>;
|
|
502
|
-
/** Default false; some S3-compatible providers need path-style. */
|
|
440
|
+
}, z.core.$strip>;
|
|
503
441
|
forcePathStyle: z.ZodDefault<z.ZodBoolean>;
|
|
504
|
-
},
|
|
505
|
-
provider: "s3";
|
|
506
|
-
bucket: string;
|
|
507
|
-
region: string;
|
|
508
|
-
credentials: {
|
|
509
|
-
accessKeyId: string;
|
|
510
|
-
secretAccessKey: string;
|
|
511
|
-
};
|
|
512
|
-
forcePathStyle: boolean;
|
|
513
|
-
endpoint?: string | undefined;
|
|
514
|
-
}, {
|
|
515
|
-
provider: "s3";
|
|
516
|
-
bucket: string;
|
|
517
|
-
region: string;
|
|
518
|
-
credentials: {
|
|
519
|
-
accessKeyId: string;
|
|
520
|
-
secretAccessKey: string;
|
|
521
|
-
};
|
|
522
|
-
endpoint?: string | undefined;
|
|
523
|
-
forcePathStyle?: boolean | undefined;
|
|
524
|
-
}>, z.ZodObject<{
|
|
442
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
525
443
|
provider: z.ZodLiteral<"r2">;
|
|
526
444
|
bucket: z.ZodString;
|
|
527
445
|
endpoint: z.ZodString;
|
|
528
446
|
credentials: z.ZodObject<{
|
|
529
447
|
accessKeyId: z.ZodString;
|
|
530
448
|
secretAccessKey: z.ZodString;
|
|
531
|
-
},
|
|
532
|
-
accessKeyId: string;
|
|
533
|
-
secretAccessKey: string;
|
|
534
|
-
}, {
|
|
535
|
-
accessKeyId: string;
|
|
536
|
-
secretAccessKey: string;
|
|
537
|
-
}>;
|
|
538
|
-
/** R2 ONLY supports path-style; the literal-true type makes that explicit. */
|
|
449
|
+
}, z.core.$strip>;
|
|
539
450
|
forcePathStyle: z.ZodLiteral<true>;
|
|
540
|
-
},
|
|
541
|
-
provider: "r2";
|
|
542
|
-
bucket: string;
|
|
543
|
-
endpoint: string;
|
|
544
|
-
credentials: {
|
|
545
|
-
accessKeyId: string;
|
|
546
|
-
secretAccessKey: string;
|
|
547
|
-
};
|
|
548
|
-
forcePathStyle: true;
|
|
549
|
-
}, {
|
|
550
|
-
provider: "r2";
|
|
551
|
-
bucket: string;
|
|
552
|
-
endpoint: string;
|
|
553
|
-
credentials: {
|
|
554
|
-
accessKeyId: string;
|
|
555
|
-
secretAccessKey: string;
|
|
556
|
-
};
|
|
557
|
-
forcePathStyle: true;
|
|
558
|
-
}>]>;
|
|
451
|
+
}, z.core.$strip>], "provider">;
|
|
559
452
|
type S3Config = z.infer<typeof S3ConfigSchema>;
|
|
560
453
|
type R2Config = z.infer<typeof R2ConfigSchema>;
|
|
561
454
|
type FileSystemConfig = z.infer<typeof FileSystemConfigSchema>;
|
|
@@ -831,11 +724,14 @@ interface FileSystem {
|
|
|
831
724
|
readonly tenantId?: string;
|
|
832
725
|
/** Optional per-tenant byte cap enforced by write-through. */
|
|
833
726
|
readonly quotaBytes?: number;
|
|
727
|
+
/** Optional per-object byte cap enforced on presigned confirm. */
|
|
728
|
+
readonly maxBytes?: number;
|
|
834
729
|
forTenant(tenantId: string): FileSystem;
|
|
835
730
|
}
|
|
836
731
|
interface CreateFileSystemOptions {
|
|
837
732
|
readonly store?: MetadataStore;
|
|
838
733
|
readonly quotaBytes?: number;
|
|
734
|
+
readonly maxBytes?: number;
|
|
839
735
|
/**
|
|
840
736
|
* When true (default), `forTenant(id)` prefixes object keys with
|
|
841
737
|
* `t/{id}/`. Set false for a single-tenant bucket or an R2 token
|
|
@@ -206,6 +206,11 @@ interface PresignedUploadInput {
|
|
|
206
206
|
contentType?: string;
|
|
207
207
|
/** Expiry in seconds. Providers enforce a max (e.g. 7 days for S3). */
|
|
208
208
|
expiresIn?: number;
|
|
209
|
+
/**
|
|
210
|
+
* When set, the signature binds `Content-Length` to this value.
|
|
211
|
+
* A PUT with any other length is rejected by the provider.
|
|
212
|
+
*/
|
|
213
|
+
contentLength?: number;
|
|
209
214
|
}
|
|
210
215
|
interface PresignedDownloadInput {
|
|
211
216
|
key: S3Key;
|
|
@@ -401,53 +406,19 @@ interface S3CompatibleAdapter {
|
|
|
401
406
|
declare const CredentialsSchema: z.ZodObject<{
|
|
402
407
|
accessKeyId: z.ZodString;
|
|
403
408
|
secretAccessKey: z.ZodString;
|
|
404
|
-
},
|
|
405
|
-
accessKeyId: string;
|
|
406
|
-
secretAccessKey: string;
|
|
407
|
-
}, {
|
|
408
|
-
accessKeyId: string;
|
|
409
|
-
secretAccessKey: string;
|
|
410
|
-
}>;
|
|
409
|
+
}, z.core.$strip>;
|
|
411
410
|
type Credentials = z.infer<typeof CredentialsSchema>;
|
|
412
411
|
declare const S3ConfigSchema: z.ZodObject<{
|
|
413
412
|
provider: z.ZodLiteral<"s3">;
|
|
414
413
|
bucket: z.ZodString;
|
|
415
414
|
region: z.ZodString;
|
|
416
|
-
/** Optional S3-compatible endpoint (MinIO, LocalStack, ...). */
|
|
417
415
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
418
416
|
credentials: z.ZodObject<{
|
|
419
417
|
accessKeyId: z.ZodString;
|
|
420
418
|
secretAccessKey: z.ZodString;
|
|
421
|
-
},
|
|
422
|
-
accessKeyId: string;
|
|
423
|
-
secretAccessKey: string;
|
|
424
|
-
}, {
|
|
425
|
-
accessKeyId: string;
|
|
426
|
-
secretAccessKey: string;
|
|
427
|
-
}>;
|
|
428
|
-
/** Default false; some S3-compatible providers need path-style. */
|
|
419
|
+
}, z.core.$strip>;
|
|
429
420
|
forcePathStyle: z.ZodDefault<z.ZodBoolean>;
|
|
430
|
-
},
|
|
431
|
-
provider: "s3";
|
|
432
|
-
bucket: string;
|
|
433
|
-
region: string;
|
|
434
|
-
credentials: {
|
|
435
|
-
accessKeyId: string;
|
|
436
|
-
secretAccessKey: string;
|
|
437
|
-
};
|
|
438
|
-
forcePathStyle: boolean;
|
|
439
|
-
endpoint?: string | undefined;
|
|
440
|
-
}, {
|
|
441
|
-
provider: "s3";
|
|
442
|
-
bucket: string;
|
|
443
|
-
region: string;
|
|
444
|
-
credentials: {
|
|
445
|
-
accessKeyId: string;
|
|
446
|
-
secretAccessKey: string;
|
|
447
|
-
};
|
|
448
|
-
endpoint?: string | undefined;
|
|
449
|
-
forcePathStyle?: boolean | undefined;
|
|
450
|
-
}>;
|
|
421
|
+
}, z.core.$strip>;
|
|
451
422
|
declare const R2ConfigSchema: z.ZodObject<{
|
|
452
423
|
provider: z.ZodLiteral<"r2">;
|
|
453
424
|
bucket: z.ZodString;
|
|
@@ -455,107 +426,29 @@ declare const R2ConfigSchema: z.ZodObject<{
|
|
|
455
426
|
credentials: z.ZodObject<{
|
|
456
427
|
accessKeyId: z.ZodString;
|
|
457
428
|
secretAccessKey: z.ZodString;
|
|
458
|
-
},
|
|
459
|
-
accessKeyId: string;
|
|
460
|
-
secretAccessKey: string;
|
|
461
|
-
}, {
|
|
462
|
-
accessKeyId: string;
|
|
463
|
-
secretAccessKey: string;
|
|
464
|
-
}>;
|
|
465
|
-
/** R2 ONLY supports path-style; the literal-true type makes that explicit. */
|
|
429
|
+
}, z.core.$strip>;
|
|
466
430
|
forcePathStyle: z.ZodLiteral<true>;
|
|
467
|
-
},
|
|
468
|
-
|
|
469
|
-
bucket: string;
|
|
470
|
-
endpoint: string;
|
|
471
|
-
credentials: {
|
|
472
|
-
accessKeyId: string;
|
|
473
|
-
secretAccessKey: string;
|
|
474
|
-
};
|
|
475
|
-
forcePathStyle: true;
|
|
476
|
-
}, {
|
|
477
|
-
provider: "r2";
|
|
478
|
-
bucket: string;
|
|
479
|
-
endpoint: string;
|
|
480
|
-
credentials: {
|
|
481
|
-
accessKeyId: string;
|
|
482
|
-
secretAccessKey: string;
|
|
483
|
-
};
|
|
484
|
-
forcePathStyle: true;
|
|
485
|
-
}>;
|
|
486
|
-
declare const FileSystemConfigSchema: z.ZodDiscriminatedUnion<"provider", [z.ZodObject<{
|
|
431
|
+
}, z.core.$strip>;
|
|
432
|
+
declare const FileSystemConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
487
433
|
provider: z.ZodLiteral<"s3">;
|
|
488
434
|
bucket: z.ZodString;
|
|
489
435
|
region: z.ZodString;
|
|
490
|
-
/** Optional S3-compatible endpoint (MinIO, LocalStack, ...). */
|
|
491
436
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
492
437
|
credentials: z.ZodObject<{
|
|
493
438
|
accessKeyId: z.ZodString;
|
|
494
439
|
secretAccessKey: z.ZodString;
|
|
495
|
-
},
|
|
496
|
-
accessKeyId: string;
|
|
497
|
-
secretAccessKey: string;
|
|
498
|
-
}, {
|
|
499
|
-
accessKeyId: string;
|
|
500
|
-
secretAccessKey: string;
|
|
501
|
-
}>;
|
|
502
|
-
/** Default false; some S3-compatible providers need path-style. */
|
|
440
|
+
}, z.core.$strip>;
|
|
503
441
|
forcePathStyle: z.ZodDefault<z.ZodBoolean>;
|
|
504
|
-
},
|
|
505
|
-
provider: "s3";
|
|
506
|
-
bucket: string;
|
|
507
|
-
region: string;
|
|
508
|
-
credentials: {
|
|
509
|
-
accessKeyId: string;
|
|
510
|
-
secretAccessKey: string;
|
|
511
|
-
};
|
|
512
|
-
forcePathStyle: boolean;
|
|
513
|
-
endpoint?: string | undefined;
|
|
514
|
-
}, {
|
|
515
|
-
provider: "s3";
|
|
516
|
-
bucket: string;
|
|
517
|
-
region: string;
|
|
518
|
-
credentials: {
|
|
519
|
-
accessKeyId: string;
|
|
520
|
-
secretAccessKey: string;
|
|
521
|
-
};
|
|
522
|
-
endpoint?: string | undefined;
|
|
523
|
-
forcePathStyle?: boolean | undefined;
|
|
524
|
-
}>, z.ZodObject<{
|
|
442
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
525
443
|
provider: z.ZodLiteral<"r2">;
|
|
526
444
|
bucket: z.ZodString;
|
|
527
445
|
endpoint: z.ZodString;
|
|
528
446
|
credentials: z.ZodObject<{
|
|
529
447
|
accessKeyId: z.ZodString;
|
|
530
448
|
secretAccessKey: z.ZodString;
|
|
531
|
-
},
|
|
532
|
-
accessKeyId: string;
|
|
533
|
-
secretAccessKey: string;
|
|
534
|
-
}, {
|
|
535
|
-
accessKeyId: string;
|
|
536
|
-
secretAccessKey: string;
|
|
537
|
-
}>;
|
|
538
|
-
/** R2 ONLY supports path-style; the literal-true type makes that explicit. */
|
|
449
|
+
}, z.core.$strip>;
|
|
539
450
|
forcePathStyle: z.ZodLiteral<true>;
|
|
540
|
-
},
|
|
541
|
-
provider: "r2";
|
|
542
|
-
bucket: string;
|
|
543
|
-
endpoint: string;
|
|
544
|
-
credentials: {
|
|
545
|
-
accessKeyId: string;
|
|
546
|
-
secretAccessKey: string;
|
|
547
|
-
};
|
|
548
|
-
forcePathStyle: true;
|
|
549
|
-
}, {
|
|
550
|
-
provider: "r2";
|
|
551
|
-
bucket: string;
|
|
552
|
-
endpoint: string;
|
|
553
|
-
credentials: {
|
|
554
|
-
accessKeyId: string;
|
|
555
|
-
secretAccessKey: string;
|
|
556
|
-
};
|
|
557
|
-
forcePathStyle: true;
|
|
558
|
-
}>]>;
|
|
451
|
+
}, z.core.$strip>], "provider">;
|
|
559
452
|
type S3Config = z.infer<typeof S3ConfigSchema>;
|
|
560
453
|
type R2Config = z.infer<typeof R2ConfigSchema>;
|
|
561
454
|
type FileSystemConfig = z.infer<typeof FileSystemConfigSchema>;
|
|
@@ -831,11 +724,14 @@ interface FileSystem {
|
|
|
831
724
|
readonly tenantId?: string;
|
|
832
725
|
/** Optional per-tenant byte cap enforced by write-through. */
|
|
833
726
|
readonly quotaBytes?: number;
|
|
727
|
+
/** Optional per-object byte cap enforced on presigned confirm. */
|
|
728
|
+
readonly maxBytes?: number;
|
|
834
729
|
forTenant(tenantId: string): FileSystem;
|
|
835
730
|
}
|
|
836
731
|
interface CreateFileSystemOptions {
|
|
837
732
|
readonly store?: MetadataStore;
|
|
838
733
|
readonly quotaBytes?: number;
|
|
734
|
+
readonly maxBytes?: number;
|
|
839
735
|
/**
|
|
840
736
|
* When true (default), `forTenant(id)` prefixes object keys with
|
|
841
737
|
* `t/{id}/`. Set false for a single-tenant bucket or an R2 token
|
package/dist/index.cjs
CHANGED
|
@@ -3080,10 +3080,16 @@ var createPresignedUploadUrl = async (client, config, input) => {
|
|
|
3080
3080
|
const cmd = new clientS3.PutObjectCommand({
|
|
3081
3081
|
Bucket: config.bucket,
|
|
3082
3082
|
Key: input.key,
|
|
3083
|
-
ContentType: input.contentType
|
|
3083
|
+
ContentType: input.contentType,
|
|
3084
|
+
ContentLength: input.contentLength
|
|
3084
3085
|
});
|
|
3085
3086
|
const url = await s3RequestPresigner.getSignedUrl(client, cmd, { expiresIn: input.expiresIn ?? 900 });
|
|
3086
|
-
|
|
3087
|
+
const requiredHeaders = {};
|
|
3088
|
+
if (input.contentType) requiredHeaders["Content-Type"] = input.contentType;
|
|
3089
|
+
if (input.contentLength != null) {
|
|
3090
|
+
requiredHeaders["Content-Length"] = String(input.contentLength);
|
|
3091
|
+
}
|
|
3092
|
+
return ok({ url, method: "PUT", requiredHeaders });
|
|
3087
3093
|
} catch (e) {
|
|
3088
3094
|
return err(fromAws(e));
|
|
3089
3095
|
}
|
|
@@ -3390,11 +3396,17 @@ function createMemoryAdapter(options = {}) {
|
|
|
3390
3396
|
};
|
|
3391
3397
|
const createPresignedUploadUrl2 = async (input) => {
|
|
3392
3398
|
const expiresIn = input.expiresIn ?? 900;
|
|
3399
|
+
const requiredHeaders = {};
|
|
3400
|
+
if (input.contentType) requiredHeaders["Content-Type"] = input.contentType;
|
|
3401
|
+
if (input.contentLength != null) {
|
|
3402
|
+
requiredHeaders["Content-Length"] = String(input.contentLength);
|
|
3403
|
+
}
|
|
3393
3404
|
return {
|
|
3394
3405
|
ok: true,
|
|
3395
3406
|
value: {
|
|
3396
3407
|
url: `in-memory://${bucket}/${input.key}?expiresIn=${expiresIn}`,
|
|
3397
|
-
method: "PUT"
|
|
3408
|
+
method: "PUT",
|
|
3409
|
+
requiredHeaders
|
|
3398
3410
|
}
|
|
3399
3411
|
};
|
|
3400
3412
|
};
|
|
@@ -3623,6 +3635,7 @@ var assemble = (adapter, config, options) => {
|
|
|
3623
3635
|
metadata: options?.store,
|
|
3624
3636
|
tenantId,
|
|
3625
3637
|
quotaBytes: options?.quotaBytes,
|
|
3638
|
+
maxBytes: options?.maxBytes,
|
|
3626
3639
|
forTenant
|
|
3627
3640
|
});
|
|
3628
3641
|
return {
|
|
@@ -3630,6 +3643,7 @@ var assemble = (adapter, config, options) => {
|
|
|
3630
3643
|
config,
|
|
3631
3644
|
metadata: options?.store,
|
|
3632
3645
|
quotaBytes: options?.quotaBytes,
|
|
3646
|
+
maxBytes: options?.maxBytes,
|
|
3633
3647
|
forTenant
|
|
3634
3648
|
};
|
|
3635
3649
|
};
|
|
@@ -4479,22 +4493,22 @@ var buildInner = (Database, options) => {
|
|
|
4479
4493
|
const stmtUpdateSelfMove = db.prepare(`
|
|
4480
4494
|
UPDATE nodes
|
|
4481
4495
|
SET parent_id = ?, name = ?, path = ?, updated_at = ?
|
|
4482
|
-
WHERE id = ?
|
|
4496
|
+
WHERE id = ? AND tenant_id = ?
|
|
4483
4497
|
`);
|
|
4484
4498
|
const stmtCascadeDescendants = db.prepare(`
|
|
4485
4499
|
UPDATE nodes
|
|
4486
4500
|
SET path = ? || SUBSTR(path, LENGTH(?) + 1), updated_at = ?
|
|
4487
|
-
WHERE path LIKE ? || '/%'
|
|
4501
|
+
WHERE tenant_id = ? AND path LIKE ? || '/%' ESCAPE '\\'
|
|
4488
4502
|
`);
|
|
4489
4503
|
const stmtTombstone = db.prepare(`
|
|
4490
4504
|
UPDATE nodes
|
|
4491
4505
|
SET deleted_at = ?, updated_at = ?
|
|
4492
|
-
WHERE id = ?
|
|
4506
|
+
WHERE id = ? AND tenant_id = ?
|
|
4493
4507
|
`);
|
|
4494
4508
|
const stmtTombstoneSubtree = db.prepare(`
|
|
4495
4509
|
UPDATE nodes
|
|
4496
4510
|
SET deleted_at = ?, updated_at = ?
|
|
4497
|
-
WHERE (id = ? OR path LIKE ? || '/%')
|
|
4511
|
+
WHERE tenant_id = ? AND (id = ? OR path LIKE ? || '/%' ESCAPE '\\')
|
|
4498
4512
|
AND deleted_at IS NULL
|
|
4499
4513
|
`);
|
|
4500
4514
|
const stmtHasLiveChild = db.prepare(`
|
|
@@ -4522,7 +4536,7 @@ var buildInner = (Database, options) => {
|
|
|
4522
4536
|
WHERE nodes_fts MATCH ?
|
|
4523
4537
|
AND n.tenant_id = ?
|
|
4524
4538
|
AND n.deleted_at IS NULL
|
|
4525
|
-
AND (n.id = ? OR n.path LIKE ? || '/%')
|
|
4539
|
+
AND (n.id = ? OR n.path LIKE ? || '/%' ESCAPE '\\')
|
|
4526
4540
|
ORDER BY bm25(nodes_fts)
|
|
4527
4541
|
LIMIT ?
|
|
4528
4542
|
`);
|
|
@@ -4559,6 +4573,7 @@ var buildInner = (Database, options) => {
|
|
|
4559
4573
|
retryable: false
|
|
4560
4574
|
})
|
|
4561
4575
|
);
|
|
4576
|
+
const escapeLike = (s) => s.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
4562
4577
|
return {
|
|
4563
4578
|
async createNode(input) {
|
|
4564
4579
|
const normalized = normalizeNodeName(input.name);
|
|
@@ -4611,7 +4626,7 @@ var buildInner = (Database, options) => {
|
|
|
4611
4626
|
return err(
|
|
4612
4627
|
new FileSystemError({
|
|
4613
4628
|
code: "InternalError",
|
|
4614
|
-
message:
|
|
4629
|
+
message: "createNode failed",
|
|
4615
4630
|
retryable: false
|
|
4616
4631
|
})
|
|
4617
4632
|
);
|
|
@@ -4698,14 +4713,16 @@ var buildInner = (Database, options) => {
|
|
|
4698
4713
|
newName,
|
|
4699
4714
|
newPath,
|
|
4700
4715
|
nowIso(),
|
|
4701
|
-
input.id
|
|
4716
|
+
input.id,
|
|
4717
|
+
input.tenantId
|
|
4702
4718
|
);
|
|
4703
4719
|
if (current.path !== newPath) {
|
|
4704
4720
|
stmtCascadeDescendants.run(
|
|
4705
4721
|
newPath,
|
|
4706
4722
|
current.path,
|
|
4707
4723
|
nowIso(),
|
|
4708
|
-
|
|
4724
|
+
input.tenantId,
|
|
4725
|
+
escapeLike(current.path)
|
|
4709
4726
|
);
|
|
4710
4727
|
}
|
|
4711
4728
|
});
|
|
@@ -4723,7 +4740,7 @@ var buildInner = (Database, options) => {
|
|
|
4723
4740
|
return err(
|
|
4724
4741
|
new FileSystemError({
|
|
4725
4742
|
code: "InternalError",
|
|
4726
|
-
message:
|
|
4743
|
+
message: "moveNode failed",
|
|
4727
4744
|
retryable: false
|
|
4728
4745
|
})
|
|
4729
4746
|
);
|
|
@@ -4757,9 +4774,9 @@ var buildInner = (Database, options) => {
|
|
|
4757
4774
|
}
|
|
4758
4775
|
const now = nowIso();
|
|
4759
4776
|
if (input.recursive || node.kind === "file") {
|
|
4760
|
-
stmtTombstoneSubtree.run(now, now, input.id, node.path);
|
|
4777
|
+
stmtTombstoneSubtree.run(now, now, input.tenantId, input.id, escapeLike(node.path));
|
|
4761
4778
|
} else {
|
|
4762
|
-
stmtTombstone.run(now, now, input.id);
|
|
4779
|
+
stmtTombstone.run(now, now, input.id, input.tenantId);
|
|
4763
4780
|
}
|
|
4764
4781
|
return ok(void 0);
|
|
4765
4782
|
},
|
|
@@ -4776,19 +4793,19 @@ var buildInner = (Database, options) => {
|
|
|
4776
4793
|
})
|
|
4777
4794
|
);
|
|
4778
4795
|
}
|
|
4779
|
-
const like = `${node.path}/%`;
|
|
4796
|
+
const like = `${escapeLike(node.path)}/%`;
|
|
4780
4797
|
const files = db.prepare(
|
|
4781
4798
|
`SELECT s3_key FROM nodes
|
|
4782
4799
|
WHERE tenant_id = ? AND deleted_at IS NOT NULL AND kind = 'file' AND s3_key != ''
|
|
4783
|
-
AND (id = ? OR path LIKE ?)`
|
|
4800
|
+
AND (id = ? OR path LIKE ? ESCAPE '\\')`
|
|
4784
4801
|
).all(input.tenantId, input.id, like);
|
|
4785
4802
|
db.prepare(
|
|
4786
4803
|
`DELETE FROM shares WHERE tenant_id = ? AND node_id IN (
|
|
4787
|
-
SELECT id FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ?)
|
|
4804
|
+
SELECT id FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ? ESCAPE '\\')
|
|
4788
4805
|
)`
|
|
4789
4806
|
).run(input.tenantId, input.tenantId, input.id, like);
|
|
4790
4807
|
db.prepare(
|
|
4791
|
-
`DELETE FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ?)`
|
|
4808
|
+
`DELETE FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ? ESCAPE '\\')`
|
|
4792
4809
|
).run(input.tenantId, input.id, like);
|
|
4793
4810
|
return ok({ s3Keys: files.map((row) => row.s3_key) });
|
|
4794
4811
|
},
|
|
@@ -4828,7 +4845,7 @@ var buildInner = (Database, options) => {
|
|
|
4828
4845
|
ftsQuery,
|
|
4829
4846
|
input.tenantId,
|
|
4830
4847
|
input.parentId,
|
|
4831
|
-
parent.path,
|
|
4848
|
+
escapeLike(parent.path),
|
|
4832
4849
|
limit
|
|
4833
4850
|
);
|
|
4834
4851
|
}
|
|
@@ -5300,7 +5317,7 @@ var buildInner2 = (pg, options) => {
|
|
|
5300
5317
|
return err(
|
|
5301
5318
|
new FileSystemError({
|
|
5302
5319
|
code: "InternalError",
|
|
5303
|
-
message:
|
|
5320
|
+
message: "createNode failed",
|
|
5304
5321
|
retryable: false
|
|
5305
5322
|
})
|
|
5306
5323
|
);
|
|
@@ -5417,16 +5434,16 @@ var buildInner2 = (pg, options) => {
|
|
|
5417
5434
|
await client.query(
|
|
5418
5435
|
`UPDATE "${schema}".nodes
|
|
5419
5436
|
SET parent_id = $1, name = $2, path = $3, updated_at = now()
|
|
5420
|
-
WHERE id = $4`,
|
|
5421
|
-
[input.newParentId, newName, newPath, input.id]
|
|
5437
|
+
WHERE id = $4 AND tenant_id = $5`,
|
|
5438
|
+
[input.newParentId, newName, newPath, input.id, input.tenantId]
|
|
5422
5439
|
);
|
|
5423
5440
|
if (current.path !== newPath) {
|
|
5424
5441
|
await client.query(
|
|
5425
5442
|
`UPDATE "${schema}".nodes
|
|
5426
5443
|
SET path = $1 || substring(path FROM length($2) + 1),
|
|
5427
5444
|
updated_at = now()
|
|
5428
|
-
WHERE path LIKE $
|
|
5429
|
-
[newPath, current.path]
|
|
5445
|
+
WHERE tenant_id = $3 AND path LIKE $4 || '/%' ESCAPE '\\'`,
|
|
5446
|
+
[newPath, current.path, input.tenantId, escapeLike(current.path)]
|
|
5430
5447
|
);
|
|
5431
5448
|
}
|
|
5432
5449
|
});
|
|
@@ -5443,7 +5460,7 @@ var buildInner2 = (pg, options) => {
|
|
|
5443
5460
|
return err(
|
|
5444
5461
|
new FileSystemError({
|
|
5445
5462
|
code: "InternalError",
|
|
5446
|
-
message:
|
|
5463
|
+
message: "moveNode failed",
|
|
5447
5464
|
retryable: false
|
|
5448
5465
|
})
|
|
5449
5466
|
);
|
|
@@ -5498,17 +5515,17 @@ var buildInner2 = (pg, options) => {
|
|
|
5498
5515
|
input.tenantId,
|
|
5499
5516
|
`UPDATE "${schema}".nodes
|
|
5500
5517
|
SET deleted_at = now(), updated_at = now()
|
|
5501
|
-
WHERE (id = $
|
|
5518
|
+
WHERE tenant_id = $1 AND (id = $2 OR path LIKE $3 || '/%' ESCAPE '\\')
|
|
5502
5519
|
AND deleted_at IS NULL`,
|
|
5503
|
-
[input.id, node.path]
|
|
5520
|
+
[input.tenantId, input.id, escapeLike(node.path)]
|
|
5504
5521
|
);
|
|
5505
5522
|
} else {
|
|
5506
5523
|
await q(
|
|
5507
5524
|
input.tenantId,
|
|
5508
5525
|
`UPDATE "${schema}".nodes
|
|
5509
5526
|
SET deleted_at = now(), updated_at = now()
|
|
5510
|
-
WHERE id = $1`,
|
|
5511
|
-
[input.id]
|
|
5527
|
+
WHERE id = $1 AND tenant_id = $2`,
|
|
5528
|
+
[input.id, input.tenantId]
|
|
5512
5529
|
);
|
|
5513
5530
|
}
|
|
5514
5531
|
return ok(void 0);
|
|
@@ -5531,26 +5548,26 @@ var buildInner2 = (pg, options) => {
|
|
|
5531
5548
|
})
|
|
5532
5549
|
);
|
|
5533
5550
|
}
|
|
5534
|
-
const like = `${node.path}/%`;
|
|
5551
|
+
const like = `${escapeLike(node.path)}/%`;
|
|
5535
5552
|
const files = await q(
|
|
5536
5553
|
input.tenantId,
|
|
5537
5554
|
`SELECT s3_key FROM "${schema}".nodes
|
|
5538
5555
|
WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND kind = 'file' AND s3_key <> ''
|
|
5539
|
-
AND (id = $2 OR path LIKE $3)`,
|
|
5556
|
+
AND (id = $2 OR path LIKE $3 ESCAPE '\\')`,
|
|
5540
5557
|
[input.tenantId, input.id, like]
|
|
5541
5558
|
);
|
|
5542
5559
|
await q(
|
|
5543
5560
|
input.tenantId,
|
|
5544
5561
|
`DELETE FROM "${schema}".shares WHERE tenant_id = $1 AND node_id IN (
|
|
5545
5562
|
SELECT id FROM "${schema}".nodes
|
|
5546
|
-
WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3)
|
|
5563
|
+
WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3 ESCAPE '\\')
|
|
5547
5564
|
)`,
|
|
5548
5565
|
[input.tenantId, input.id, like]
|
|
5549
5566
|
);
|
|
5550
5567
|
await q(
|
|
5551
5568
|
input.tenantId,
|
|
5552
5569
|
`DELETE FROM "${schema}".nodes
|
|
5553
|
-
WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3)`,
|
|
5570
|
+
WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3 ESCAPE '\\')`,
|
|
5554
5571
|
[input.tenantId, input.id, like]
|
|
5555
5572
|
);
|
|
5556
5573
|
return ok({ s3Keys: files.rows.map((row) => row.s3_key) });
|
|
@@ -5624,11 +5641,11 @@ var buildInner2 = (pg, options) => {
|
|
|
5624
5641
|
input.tenantId,
|
|
5625
5642
|
`SELECT * FROM "${schema}".nodes
|
|
5626
5643
|
WHERE tenant_id = $1 AND deleted_at IS NULL
|
|
5627
|
-
AND (id = $2 OR path LIKE $3 || '/%')
|
|
5644
|
+
AND (id = $2 OR path LIKE $3 || '/%' ESCAPE '\\')
|
|
5628
5645
|
AND name ILIKE $4 ESCAPE '\\'
|
|
5629
5646
|
ORDER BY lower(name) ASC
|
|
5630
5647
|
LIMIT $5`,
|
|
5631
|
-
[input.tenantId, input.parentId, parent.path, pattern, limit]
|
|
5648
|
+
[input.tenantId, input.parentId, escapeLike(parent.path), pattern, limit]
|
|
5632
5649
|
);
|
|
5633
5650
|
}
|
|
5634
5651
|
}
|