@shipstatic/types 0.9.9 → 0.9.10

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.d.ts CHANGED
@@ -692,7 +692,8 @@ export interface DeploymentUploadOptions {
692
692
  * Optional password that protects this deployment.
693
693
  *
694
694
  * Length: {@link PASSWORD_CONSTRAINTS.MIN_LENGTH} to
695
- * {@link PASSWORD_CONSTRAINTS.MAX_LENGTH} characters; whitespace is
695
+ * {@link PASSWORD_CONSTRAINTS.MAX_LENGTH} characters. Leading and trailing
696
+ * whitespace is trimmed before validation; internal whitespace is
696
697
  * significant. Visitors are prompted to enter the password before they can
697
698
  * view the deployment — including on any custom domains pointing at it.
698
699
  * To remove protection, redeploy without a password.
@@ -1015,10 +1016,18 @@ export declare const PASSWORD_CONSTRAINTS: {
1015
1016
  /**
1016
1017
  * Validate an optional deployment password and return it normalized.
1017
1018
  *
1018
- * Absent (`undefined` / `null`) → returns `undefined`; an unprotected
1019
- * deployment is a valid choice. Present → must be a string within
1020
- * `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim
1021
- * significant. Throws `ShipError.validation` on breach.
1019
+ * Absent (`undefined` / `null`) → returns `undefined`. Present → trim
1020
+ * leading/trailing whitespace, then validate against `PASSWORD_CONSTRAINTS`
1021
+ * length bounds (internal whitespace is significant and counts toward
1022
+ * length). Throws `ShipError.validation` on breach; returns the trimmed
1023
+ * value.
1024
+ *
1025
+ * The trim is canonical: at upload, the API hashes the trimmed value; at
1026
+ * unlock, the router trims submissions before hashing. Submission and storage
1027
+ * agree byte-for-byte. Length validation runs on the trimmed value because
1028
+ * that's the user's actual intent — and it disarms a class of invisible
1029
+ * foot-guns (trailing newlines from copy/paste, mobile auto-spacing,
1030
+ * password-manager artifacts).
1022
1031
  *
1023
1032
  * Single source of truth shared by SDK (client-side validation, return
1024
1033
  * ignored) and API (server-side enforcement, return threaded into config).
package/dist/index.js CHANGED
@@ -664,10 +664,18 @@ export const PASSWORD_CONSTRAINTS = {
664
664
  /**
665
665
  * Validate an optional deployment password and return it normalized.
666
666
  *
667
- * Absent (`undefined` / `null`) → returns `undefined`; an unprotected
668
- * deployment is a valid choice. Present → must be a string within
669
- * `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim
670
- * significant. Throws `ShipError.validation` on breach.
667
+ * Absent (`undefined` / `null`) → returns `undefined`. Present → trim
668
+ * leading/trailing whitespace, then validate against `PASSWORD_CONSTRAINTS`
669
+ * length bounds (internal whitespace is significant and counts toward
670
+ * length). Throws `ShipError.validation` on breach; returns the trimmed
671
+ * value.
672
+ *
673
+ * The trim is canonical: at upload, the API hashes the trimmed value; at
674
+ * unlock, the router trims submissions before hashing. Submission and storage
675
+ * agree byte-for-byte. Length validation runs on the trimmed value because
676
+ * that's the user's actual intent — and it disarms a class of invisible
677
+ * foot-guns (trailing newlines from copy/paste, mobile auto-spacing,
678
+ * password-manager artifacts).
671
679
  *
672
680
  * Single source of truth shared by SDK (client-side validation, return
673
681
  * ignored) and API (server-side enforcement, return threaded into config).
@@ -680,9 +688,10 @@ export function validatePassword(value) {
680
688
  if (typeof value !== 'string') {
681
689
  throw ShipError.validation('Password must be a string');
682
690
  }
683
- if (value.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
684
- value.length > PASSWORD_CONSTRAINTS.MAX_LENGTH) {
691
+ const trimmed = value.trim();
692
+ if (trimmed.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
693
+ trimmed.length > PASSWORD_CONSTRAINTS.MAX_LENGTH) {
685
694
  throw ShipError.validation(`Password must be between ${PASSWORD_CONSTRAINTS.MIN_LENGTH} and ${PASSWORD_CONSTRAINTS.MAX_LENGTH} characters`);
686
695
  }
687
- return value;
696
+ return trimmed;
688
697
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "Shared types for ShipStatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -1065,7 +1065,8 @@ export interface DeploymentUploadOptions {
1065
1065
  * Optional password that protects this deployment.
1066
1066
  *
1067
1067
  * Length: {@link PASSWORD_CONSTRAINTS.MIN_LENGTH} to
1068
- * {@link PASSWORD_CONSTRAINTS.MAX_LENGTH} characters; whitespace is
1068
+ * {@link PASSWORD_CONSTRAINTS.MAX_LENGTH} characters. Leading and trailing
1069
+ * whitespace is trimmed before validation; internal whitespace is
1069
1070
  * significant. Visitors are prompted to enter the password before they can
1070
1071
  * view the deployment — including on any custom domains pointing at it.
1071
1072
  * To remove protection, redeploy without a password.
@@ -1529,10 +1530,18 @@ export const PASSWORD_CONSTRAINTS = {
1529
1530
  /**
1530
1531
  * Validate an optional deployment password and return it normalized.
1531
1532
  *
1532
- * Absent (`undefined` / `null`) → returns `undefined`; an unprotected
1533
- * deployment is a valid choice. Present → must be a string within
1534
- * `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim
1535
- * significant. Throws `ShipError.validation` on breach.
1533
+ * Absent (`undefined` / `null`) → returns `undefined`. Present → trim
1534
+ * leading/trailing whitespace, then validate against `PASSWORD_CONSTRAINTS`
1535
+ * length bounds (internal whitespace is significant and counts toward
1536
+ * length). Throws `ShipError.validation` on breach; returns the trimmed
1537
+ * value.
1538
+ *
1539
+ * The trim is canonical: at upload, the API hashes the trimmed value; at
1540
+ * unlock, the router trims submissions before hashing. Submission and storage
1541
+ * agree byte-for-byte. Length validation runs on the trimmed value because
1542
+ * that's the user's actual intent — and it disarms a class of invisible
1543
+ * foot-guns (trailing newlines from copy/paste, mobile auto-spacing,
1544
+ * password-manager artifacts).
1536
1545
  *
1537
1546
  * Single source of truth shared by SDK (client-side validation, return
1538
1547
  * ignored) and API (server-side enforcement, return threaded into config).
@@ -1544,13 +1553,14 @@ export function validatePassword(value: unknown): string | undefined {
1544
1553
  if (typeof value !== 'string') {
1545
1554
  throw ShipError.validation('Password must be a string');
1546
1555
  }
1556
+ const trimmed = value.trim();
1547
1557
  if (
1548
- value.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
1549
- value.length > PASSWORD_CONSTRAINTS.MAX_LENGTH
1558
+ trimmed.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
1559
+ trimmed.length > PASSWORD_CONSTRAINTS.MAX_LENGTH
1550
1560
  ) {
1551
1561
  throw ShipError.validation(
1552
1562
  `Password must be between ${PASSWORD_CONSTRAINTS.MIN_LENGTH} and ${PASSWORD_CONSTRAINTS.MAX_LENGTH} characters`,
1553
1563
  );
1554
1564
  }
1555
- return value;
1565
+ return trimmed;
1556
1566
  }