@palbase/backend 8.1.0 → 8.2.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/dist/index.cjs +0 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -18
- package/dist/index.d.ts +20 -18
- package/dist/index.js +0 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -714,20 +714,18 @@ type ParameterDecorator$1 = (target: object, propertyKey: string | symbol, param
|
|
|
714
714
|
* — the client cannot exceed what it declared.
|
|
715
715
|
*/
|
|
716
716
|
interface UploadConfig {
|
|
717
|
-
/** Target bucket NAME. MUST exist in `config/storage.ts` `defineStorage(...)`. */
|
|
718
|
-
bucket: string;
|
|
719
|
-
/**
|
|
720
|
-
* Max object size in BYTES. Enforced twice: the authorize pre-flight rejects a
|
|
721
|
-
* larger declared size, and the signed URL pins it so storage rejects a larger
|
|
722
|
-
* PUT. When omitted, the bucket's own `fileSizeLimit` applies.
|
|
723
|
-
*/
|
|
724
|
-
maxSize?: number;
|
|
725
717
|
/**
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
718
|
+
* Target bucket NAME. MUST exist in `config/storage.ts` `defineStorage(...)`.
|
|
719
|
+
*
|
|
720
|
+
* The bucket is the SINGLE SOURCE OF TRUTH for the size limit + MIME allowlist:
|
|
721
|
+
* `bucket({ fileSizeLimit, allowedMimeTypes })`. Storage enforces those at the
|
|
722
|
+
* actual PUT (the only guard a client cannot skip), so `@Upload` deliberately
|
|
723
|
+
* does NOT take its own `maxSize`/`allowedTypes` — duplicating them here would
|
|
724
|
+
* let a route declare a tighter limit than its bucket that storage would not
|
|
725
|
+
* enforce (a real bypass: declare 10 bytes at authorize, then PUT up to the
|
|
726
|
+
* bucket ceiling straight at the signed URL). One bucket, one limit, enforced.
|
|
729
727
|
*/
|
|
730
|
-
|
|
728
|
+
bucket: string;
|
|
731
729
|
/**
|
|
732
730
|
* SERVER-side object key template. The client NEVER chooses the path. Tokens:
|
|
733
731
|
* `{userId}` (authenticated user id), `{uploadId}` (server-minted), and
|
|
@@ -742,9 +740,10 @@ interface UploadConfig {
|
|
|
742
740
|
* guard + signed-URL pinning.
|
|
743
741
|
*
|
|
744
742
|
* @example
|
|
745
|
-
* @Upload("/", { bucket: "docs",
|
|
746
|
-
* allowedTypes: ["application/pdf"], pathTemplate: "{userId}/{uploadId}-{filename}" })
|
|
743
|
+
* @Upload("/", { bucket: "docs", pathTemplate: "{userId}/{uploadId}-{filename}" })
|
|
747
744
|
* async upload(@UploadedObject() obj: UploadedObject, @User() user): Promise<DocResult> { ... }
|
|
745
|
+
* // The size limit + MIME allowlist come from the "docs" bucket in
|
|
746
|
+
* // config/storage.ts — storage enforces them at the PUT.
|
|
748
747
|
*/
|
|
749
748
|
declare function Upload(subpath: string, config: UploadConfig & Pick<RouteOptions, "auth" | "rateLimit">): MethodDecorator$1;
|
|
750
749
|
/**
|
|
@@ -777,10 +776,13 @@ interface UploadedObject {
|
|
|
777
776
|
declare function UploadedObject(): ParameterDecorator$1;
|
|
778
777
|
/**
|
|
779
778
|
* Cross-check one `@Upload` route's uploadConfig against the project's
|
|
780
|
-
* {@link StorageConfig}: the bucket
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
779
|
+
* {@link StorageConfig}: the named bucket MUST exist in `defineStorage(...)`.
|
|
780
|
+
* Throws a precise error so a typo fails at deploy, not at the first user upload.
|
|
781
|
+
*
|
|
782
|
+
* That is the ONLY cross-check: the size limit + MIME allowlist live on the
|
|
783
|
+
* bucket (`bucket({ fileSizeLimit, allowedMimeTypes })`) and are enforced by
|
|
784
|
+
* storage at the PUT. `@Upload` carries no `maxSize`/`allowedTypes` of its own,
|
|
785
|
+
* so there is nothing to compare — one bucket, one limit, no drift.
|
|
784
786
|
*
|
|
785
787
|
* `routeLabel` is used only for error messages (e.g. `docs.upload`).
|
|
786
788
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -714,20 +714,18 @@ type ParameterDecorator$1 = (target: object, propertyKey: string | symbol, param
|
|
|
714
714
|
* — the client cannot exceed what it declared.
|
|
715
715
|
*/
|
|
716
716
|
interface UploadConfig {
|
|
717
|
-
/** Target bucket NAME. MUST exist in `config/storage.ts` `defineStorage(...)`. */
|
|
718
|
-
bucket: string;
|
|
719
|
-
/**
|
|
720
|
-
* Max object size in BYTES. Enforced twice: the authorize pre-flight rejects a
|
|
721
|
-
* larger declared size, and the signed URL pins it so storage rejects a larger
|
|
722
|
-
* PUT. When omitted, the bucket's own `fileSizeLimit` applies.
|
|
723
|
-
*/
|
|
724
|
-
maxSize?: number;
|
|
725
717
|
/**
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
718
|
+
* Target bucket NAME. MUST exist in `config/storage.ts` `defineStorage(...)`.
|
|
719
|
+
*
|
|
720
|
+
* The bucket is the SINGLE SOURCE OF TRUTH for the size limit + MIME allowlist:
|
|
721
|
+
* `bucket({ fileSizeLimit, allowedMimeTypes })`. Storage enforces those at the
|
|
722
|
+
* actual PUT (the only guard a client cannot skip), so `@Upload` deliberately
|
|
723
|
+
* does NOT take its own `maxSize`/`allowedTypes` — duplicating them here would
|
|
724
|
+
* let a route declare a tighter limit than its bucket that storage would not
|
|
725
|
+
* enforce (a real bypass: declare 10 bytes at authorize, then PUT up to the
|
|
726
|
+
* bucket ceiling straight at the signed URL). One bucket, one limit, enforced.
|
|
729
727
|
*/
|
|
730
|
-
|
|
728
|
+
bucket: string;
|
|
731
729
|
/**
|
|
732
730
|
* SERVER-side object key template. The client NEVER chooses the path. Tokens:
|
|
733
731
|
* `{userId}` (authenticated user id), `{uploadId}` (server-minted), and
|
|
@@ -742,9 +740,10 @@ interface UploadConfig {
|
|
|
742
740
|
* guard + signed-URL pinning.
|
|
743
741
|
*
|
|
744
742
|
* @example
|
|
745
|
-
* @Upload("/", { bucket: "docs",
|
|
746
|
-
* allowedTypes: ["application/pdf"], pathTemplate: "{userId}/{uploadId}-{filename}" })
|
|
743
|
+
* @Upload("/", { bucket: "docs", pathTemplate: "{userId}/{uploadId}-{filename}" })
|
|
747
744
|
* async upload(@UploadedObject() obj: UploadedObject, @User() user): Promise<DocResult> { ... }
|
|
745
|
+
* // The size limit + MIME allowlist come from the "docs" bucket in
|
|
746
|
+
* // config/storage.ts — storage enforces them at the PUT.
|
|
748
747
|
*/
|
|
749
748
|
declare function Upload(subpath: string, config: UploadConfig & Pick<RouteOptions, "auth" | "rateLimit">): MethodDecorator$1;
|
|
750
749
|
/**
|
|
@@ -777,10 +776,13 @@ interface UploadedObject {
|
|
|
777
776
|
declare function UploadedObject(): ParameterDecorator$1;
|
|
778
777
|
/**
|
|
779
778
|
* Cross-check one `@Upload` route's uploadConfig against the project's
|
|
780
|
-
* {@link StorageConfig}: the bucket
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
779
|
+
* {@link StorageConfig}: the named bucket MUST exist in `defineStorage(...)`.
|
|
780
|
+
* Throws a precise error so a typo fails at deploy, not at the first user upload.
|
|
781
|
+
*
|
|
782
|
+
* That is the ONLY cross-check: the size limit + MIME allowlist live on the
|
|
783
|
+
* bucket (`bucket({ fileSizeLimit, allowedMimeTypes })`) and are enforced by
|
|
784
|
+
* storage at the PUT. `@Upload` carries no `maxSize`/`allowedTypes` of its own,
|
|
785
|
+
* so there is nothing to compare — one bucket, one limit, no drift.
|
|
784
786
|
*
|
|
785
787
|
* `routeLabel` is used only for error messages (e.g. `docs.upload`).
|
|
786
788
|
*/
|
package/dist/index.js
CHANGED
|
@@ -476,7 +476,6 @@ var Patch = makeMethodDecorator("PATCH");
|
|
|
476
476
|
var Delete = makeMethodDecorator("DELETE");
|
|
477
477
|
|
|
478
478
|
// src/decorators/upload.ts
|
|
479
|
-
var MIME_RE2 = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*\/[A-Za-z0-9*][A-Za-z0-9!#$&^_.+-]*$/;
|
|
480
479
|
function Upload(subpath, config) {
|
|
481
480
|
const { auth: auth2, rateLimit, ...uploadConfig } = config;
|
|
482
481
|
validateUploadConfigShape(uploadConfig);
|
|
@@ -507,21 +506,6 @@ function validateUploadConfigShape(c) {
|
|
|
507
506
|
if (typeof c.pathTemplate !== "string" || c.pathTemplate.length === 0) {
|
|
508
507
|
throw new Error("@Upload config.pathTemplate must be a non-empty key template");
|
|
509
508
|
}
|
|
510
|
-
if (c.maxSize !== void 0) {
|
|
511
|
-
if (!Number.isInteger(c.maxSize) || c.maxSize <= 0) {
|
|
512
|
-
throw new Error(`@Upload config.maxSize must be a positive integer byte count, got ${c.maxSize}`);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
if (c.allowedTypes !== void 0) {
|
|
516
|
-
if (!Array.isArray(c.allowedTypes) || c.allowedTypes.length === 0) {
|
|
517
|
-
throw new Error("@Upload config.allowedTypes must be a non-empty array of MIME types when present");
|
|
518
|
-
}
|
|
519
|
-
for (const t of c.allowedTypes) {
|
|
520
|
-
if (typeof t !== "string" || !MIME_RE2.test(t.trim())) {
|
|
521
|
-
throw new Error(`@Upload config.allowedTypes entry "${t}" is not a valid MIME type (e.g. "image/png")`);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
509
|
}
|
|
526
510
|
function validateUploadAgainstStorage(uploadConfig, storage2, routeLabel) {
|
|
527
511
|
const def = storage2.buckets[uploadConfig.bucket];
|
|
@@ -531,28 +515,6 @@ function validateUploadAgainstStorage(uploadConfig, storage2, routeLabel) {
|
|
|
531
515
|
`@Upload route ${routeLabel} targets bucket "${uploadConfig.bucket}" which is not declared in defineStorage(...). ` + (known.length ? `Known buckets: ${known.join(", ")}.` : "No buckets are declared.")
|
|
532
516
|
);
|
|
533
517
|
}
|
|
534
|
-
if (uploadConfig.maxSize !== void 0 && def.fileSizeLimit !== null && uploadConfig.maxSize > def.fileSizeLimit) {
|
|
535
|
-
throw new Error(
|
|
536
|
-
`@Upload route ${routeLabel} maxSize (${uploadConfig.maxSize} bytes) exceeds bucket "${uploadConfig.bucket}" fileSizeLimit (${def.fileSizeLimit} bytes)`
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
if (uploadConfig.allowedTypes !== void 0 && def.allowedMimeTypes !== null) {
|
|
540
|
-
const bucketAllows = (mime) => def.allowedMimeTypes.some((b) => {
|
|
541
|
-
if (b === mime) return true;
|
|
542
|
-
const slash = b.indexOf("/");
|
|
543
|
-
if (slash > 0 && b.slice(slash + 1) === "*") {
|
|
544
|
-
return mime.startsWith(b.slice(0, slash + 1));
|
|
545
|
-
}
|
|
546
|
-
return false;
|
|
547
|
-
});
|
|
548
|
-
for (const t of uploadConfig.allowedTypes) {
|
|
549
|
-
if (!bucketAllows(t)) {
|
|
550
|
-
throw new Error(
|
|
551
|
-
`@Upload route ${routeLabel} allows MIME "${t}" which bucket "${uploadConfig.bucket}" does not (bucket allows: ${def.allowedMimeTypes.join(", ")})`
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
518
|
}
|
|
557
519
|
|
|
558
520
|
// src/decorators/params.ts
|