@sparkvault/sdk-mobile 6.0.2 → 7.0.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.
Files changed (148) hide show
  1. package/README.md +5 -5
  2. package/dist/account.d.ts +4 -3
  3. package/dist/account.js +16 -11
  4. package/dist/account.js.map +1 -1
  5. package/dist/app-sdk/email-address.d.ts +37 -0
  6. package/dist/app-sdk/email-address.js +91 -0
  7. package/dist/app-sdk/email-address.js.map +1 -0
  8. package/dist/app-sdk/encoding.d.ts +64 -0
  9. package/dist/app-sdk/encoding.js +245 -0
  10. package/dist/app-sdk/encoding.js.map +1 -0
  11. package/dist/app-sdk/entropy-contract.d.ts +33 -0
  12. package/dist/app-sdk/entropy-contract.js +51 -0
  13. package/dist/app-sdk/entropy-contract.js.map +1 -0
  14. package/dist/app-sdk/filename.d.ts +93 -0
  15. package/dist/app-sdk/filename.js +161 -0
  16. package/dist/app-sdk/filename.js.map +1 -0
  17. package/dist/app-sdk/forge-url.d.ts +107 -0
  18. package/dist/app-sdk/forge-url.js +222 -0
  19. package/dist/app-sdk/forge-url.js.map +1 -0
  20. package/dist/app-sdk/ids.d.ts +48 -0
  21. package/dist/app-sdk/ids.js +65 -0
  22. package/dist/app-sdk/ids.js.map +1 -0
  23. package/dist/app-sdk/ingot-access-log.d.ts +29 -0
  24. package/dist/app-sdk/ingot-access-log.js +49 -0
  25. package/dist/app-sdk/ingot-access-log.js.map +1 -0
  26. package/dist/app-sdk/phone.d.ts +37 -0
  27. package/dist/app-sdk/phone.js +134 -0
  28. package/dist/app-sdk/phone.js.map +1 -0
  29. package/dist/app-sdk/platform-domains.d.ts +41 -0
  30. package/dist/app-sdk/platform-domains.js +82 -0
  31. package/dist/app-sdk/platform-domains.js.map +1 -0
  32. package/dist/app-sdk/request-path.d.ts +49 -0
  33. package/dist/app-sdk/request-path.js +81 -0
  34. package/dist/app-sdk/request-path.js.map +1 -0
  35. package/dist/app-sdk/transient.d.ts +23 -0
  36. package/dist/app-sdk/transient.js +29 -0
  37. package/dist/app-sdk/transient.js.map +1 -0
  38. package/dist/app-sdk/vat-refusal.d.ts +66 -0
  39. package/dist/app-sdk/vat-refusal.js +69 -0
  40. package/dist/app-sdk/vat-refusal.js.map +1 -0
  41. package/dist/billing.d.ts +9 -17
  42. package/dist/billing.js +14 -17
  43. package/dist/billing.js.map +1 -1
  44. package/dist/config.d.ts +7 -1
  45. package/dist/config.js +10 -17
  46. package/dist/config.js.map +1 -1
  47. package/dist/encoding.d.ts +30 -4
  48. package/dist/encoding.js +89 -83
  49. package/dist/encoding.js.map +1 -1
  50. package/dist/entropy.d.ts +25 -4
  51. package/dist/entropy.js +62 -15
  52. package/dist/entropy.js.map +1 -1
  53. package/dist/entropy.test-d.d.ts +40 -0
  54. package/dist/entropy.test-d.js +12 -0
  55. package/dist/entropy.test-d.js.map +1 -0
  56. package/dist/errors.d.ts +67 -17
  57. package/dist/errors.js +70 -27
  58. package/dist/errors.js.map +1 -1
  59. package/dist/folders.js +8 -7
  60. package/dist/folders.js.map +1 -1
  61. package/dist/http.d.ts +57 -15
  62. package/dist/http.js +125 -138
  63. package/dist/http.js.map +1 -1
  64. package/dist/identity-dialog.js +4 -30
  65. package/dist/identity-dialog.js.map +1 -1
  66. package/dist/identity-input.d.ts +39 -0
  67. package/dist/identity-input.js +59 -0
  68. package/dist/identity-input.js.map +1 -0
  69. package/dist/index.d.ts +6 -5
  70. package/dist/index.js +4 -3
  71. package/dist/index.js.map +1 -1
  72. package/dist/ingots.d.ts +51 -18
  73. package/dist/ingots.js +132 -122
  74. package/dist/ingots.js.map +1 -1
  75. package/dist/mutex.d.ts +1 -2
  76. package/dist/mutex.js +0 -6
  77. package/dist/mutex.js.map +1 -1
  78. package/dist/notify.d.ts +7 -2
  79. package/dist/notify.js +12 -15
  80. package/dist/notify.js.map +1 -1
  81. package/dist/notify.test-d.d.ts +3 -2
  82. package/dist/notify.test-d.js +1 -1
  83. package/dist/products/identity.d.ts +5 -0
  84. package/dist/products/identity.js +40 -35
  85. package/dist/products/identity.js.map +1 -1
  86. package/dist/request-path.d.ts +32 -0
  87. package/dist/request-path.js +35 -0
  88. package/dist/request-path.js.map +1 -0
  89. package/dist/sparks.js +16 -15
  90. package/dist/sparks.js.map +1 -1
  91. package/dist/tus.d.ts +19 -2
  92. package/dist/tus.js +86 -35
  93. package/dist/tus.js.map +1 -1
  94. package/dist/types.d.ts +167 -15
  95. package/dist/users.d.ts +12 -5
  96. package/dist/users.js +27 -19
  97. package/dist/users.js.map +1 -1
  98. package/dist/validation.d.ts +20 -5
  99. package/dist/validation.js +29 -27
  100. package/dist/validation.js.map +1 -1
  101. package/dist/vaults.d.ts +34 -83
  102. package/dist/vaults.js +64 -44
  103. package/dist/vaults.js.map +1 -1
  104. package/dist/vaults.test-d.d.ts +22 -0
  105. package/dist/vaults.test-d.js +14 -0
  106. package/dist/vaults.test-d.js.map +1 -0
  107. package/package.json +4 -2
  108. package/src/account.ts +16 -11
  109. package/src/app-sdk/email-address.js +94 -0
  110. package/src/app-sdk/encoding.js +250 -0
  111. package/src/app-sdk/entropy-contract.js +56 -0
  112. package/src/app-sdk/filename.js +174 -0
  113. package/src/app-sdk/forge-url.js +224 -0
  114. package/src/app-sdk/ids.js +71 -0
  115. package/src/app-sdk/ingot-access-log.js +51 -0
  116. package/src/app-sdk/phone.js +139 -0
  117. package/src/app-sdk/platform-domains.js +99 -0
  118. package/src/app-sdk/request-path.js +81 -0
  119. package/src/app-sdk/transient.js +30 -0
  120. package/src/app-sdk/vat-refusal.js +74 -0
  121. package/src/billing.ts +16 -25
  122. package/src/config.ts +16 -23
  123. package/src/encoding.ts +91 -103
  124. package/src/entropy.test-d.ts +47 -0
  125. package/src/entropy.ts +86 -20
  126. package/src/errors.ts +93 -33
  127. package/src/folders.ts +8 -7
  128. package/src/http.ts +145 -150
  129. package/src/identity-dialog.tsx +4 -37
  130. package/src/identity-input.ts +70 -0
  131. package/src/index.ts +11 -3
  132. package/src/ingots.ts +173 -159
  133. package/src/mutex.ts +1 -8
  134. package/src/notify.test-d.ts +3 -1
  135. package/src/notify.ts +19 -17
  136. package/src/products/identity.ts +45 -39
  137. package/src/request-path.ts +45 -0
  138. package/src/sparks.ts +16 -13
  139. package/src/tus.ts +90 -37
  140. package/src/types.ts +165 -15
  141. package/src/users.ts +27 -17
  142. package/src/validation.ts +30 -24
  143. package/src/vaults.test-d.ts +29 -0
  144. package/src/vaults.ts +87 -153
  145. package/dist/platform-domains.generated.d.ts +0 -2
  146. package/dist/platform-domains.generated.js +0 -16
  147. package/dist/platform-domains.generated.js.map +0 -1
  148. package/src/platform-domains.generated.ts +0 -17
package/dist/users.js CHANGED
@@ -1,11 +1,13 @@
1
+ import { apiPath } from './request-path.js';
2
+ import { validateResourceId } from './validation.js';
1
3
  /**
2
4
  * Organization team client (member admins only — the API gates these on the
3
5
  * admin role and returns 403 otherwise).
4
6
  *
5
- * Licensing is a billing action (flex: nothing charges mid-cycle — the renewal
6
- * bills each cycle's unique license holders), so the only seat-affecting
7
- * operation exposed here is `invite`, which defaults new members to
8
- * `unlicensed` and never charges. Assigning or changing a paid license is
7
+ * Licensing is a billing action (licenses are prepaid: assigning or upgrading
8
+ * one charges the rest of the current billing period at once), so the only
9
+ * seat-affecting operation exposed here is `invite`, which defaults new members
10
+ * to `unlicensed` and never charges. Assigning or changing a paid license is
9
11
  * intentionally absent — clients route that to the web dashboard so native
10
12
  * apps never initiate an out-of-band purchase.
11
13
  */
@@ -15,32 +17,38 @@ export class MobileUsersClient {
15
17
  }
16
18
  /** List organization members (active and invited), with optional search/filter. */
17
19
  async list(options = {}) {
18
- const params = new URLSearchParams();
19
- if (options.search)
20
- params.set('search', options.search);
21
- if (options.status)
22
- params.set('status', options.status);
23
- if (typeof options.limit === 'number')
24
- params.set('limit', String(options.limit));
25
- if (options.cursor)
26
- params.set('cursor', options.cursor);
27
- const query = params.toString();
28
- const response = await this.http.get(query ? `/users?${query}` : '/users');
20
+ const response = await this.http.get(apiPath `/users`, {
21
+ query: {
22
+ search: options.search,
23
+ status: options.status,
24
+ limit: typeof options.limit === 'number' ? options.limit : undefined,
25
+ cursor: options.cursor,
26
+ },
27
+ });
29
28
  return response.data;
30
29
  }
31
30
  /** Invite a coworker by email. Defaults to an unlicensed seat (no charge). */
32
31
  async invite(request) {
33
- const response = await this.http.post('/users/invite', request);
32
+ const response = await this.http.post(apiPath `/users/invite`, request);
34
33
  return response.data;
35
34
  }
36
- /** Remove a member and revoke their DVAKs. Access ends immediately; the current cycle still bills them, and they stop counting next cycle. */
35
+ /**
36
+ * Remove a member and revoke their DVAKs. Access ends immediately. A license
37
+ * they held stays paid until the end of the billing period — nothing is
38
+ * refunded — and is not renewed; until then it can be given to someone else
39
+ * at no charge. `wind_down` is true when this removal ends the
40
+ * subscription — theirs was the last license it renews, and it was not
41
+ * already set to end: it ends at the period end.
42
+ */
37
43
  async remove(userId) {
38
- const response = await this.http.delete(`/users/${userId}`);
44
+ validateResourceId(userId, 'user ID', 'userId');
45
+ const response = await this.http.delete(apiPath `/users/${userId}`);
39
46
  return response.data;
40
47
  }
41
48
  /** Resend a pending invitation email (resets the 7-day expiry). */
42
49
  async resendInvite(userId) {
43
- const response = await this.http.post(`/users/${userId}/resend-invite`);
50
+ validateResourceId(userId, 'user ID', 'userId');
51
+ const response = await this.http.post(apiPath `/users/${userId}/resend-invite`);
44
52
  return response.data;
45
53
  }
46
54
  }
package/dist/users.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"users.js","sourceRoot":"","sources":["../src/users.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,iBAAiB;IAG5B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,IAAI,CAAC,UAA8B,EAAE;QACzC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAClF,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAClC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CACrC,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,MAAM,CAAC,OAA4B;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAuB,eAAe,EAAE,OAAO,CAAC,CAAC;QACtF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,8IAA8I;IAC9I,KAAK,CAAC,MAAM,CAAC,MAAc;QACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAuB,UAAU,MAAM,EAAE,CAAC,CAAC;QAClF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAuB,UAAU,MAAM,gBAAgB,CAAC,CAAC;QAC9F,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../src/users.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,iBAAiB;IAG5B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,IAAI,CAAC,UAA8B,EAAE;QACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAsB,OAAO,CAAA,QAAQ,EAAE;YACzE,KAAK,EAAE;gBACL,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,KAAK,EAAE,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBACpE,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB;SACF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,MAAM,CAAC,OAA4B;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAuB,OAAO,CAAA,eAAe,EAAE,OAAO,CAAC,CAAC;QAC7F,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CAAC,MAAc;QACzB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAuB,OAAO,CAAA,UAAU,MAAM,EAAE,CAAC,CAAC;QACzF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAuB,OAAO,CAAA,UAAU,MAAM,gBAAgB,CAAC,CAAC;QACrG,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
@@ -1,11 +1,26 @@
1
- export declare function isSafeId(id: string): boolean;
1
+ import { isResourceId } from './app-sdk/ids.js';
2
+ /** Whether a value is a well-formed SparkVault resource id (the platform's one rule). */
3
+ export { isResourceId as isSafeId };
4
+ /**
5
+ * Refuse a value that is not a SparkVault resource id before it names a route.
6
+ *
7
+ * @param label - How the message names the id, e.g. 'spark ID'.
8
+ * @param field - The argument's name, reported in the error details.
9
+ */
10
+ export declare function validateResourceId(value: unknown, label: string, field: string): void;
2
11
  export declare function validateVaultId(vaultId: string): void;
3
12
  export declare function validateIngotId(ingotId: string): void;
4
13
  export declare function validateFolderId(folderId: string): void;
5
14
  /**
6
- * Sanitize a filename to prevent path traversal and other security issues:
7
- * removes null bytes and control characters, strips path traversal sequences,
8
- * replaces directory separators, strips leading dots (hidden files), and
9
- * prefixes Windows reserved names. Falls back to 'file' when nothing remains.
15
+ * The file name to store or save text under, by the platform's one file-name
16
+ * rule (@sparkvault/app-sdk/filename, mirrored into ./app-sdk/filename.js):
17
+ * path separators, control characters and the bidi controls that disguise an
18
+ * extension (`invoice<U+202E>fdp.exe` shows as `invoiceexe.pdf`) become `_`,
19
+ * and so do the characters SparkVault refuses in a name (: * ? " < > |), so a
20
+ * name derived from a note's title uploads. With every separator gone no name
21
+ * can climb a directory, so a `..` inside a name is kept. On top of the rule,
22
+ * for the device's file system: leading dots are stripped (a hidden file) and
23
+ * Windows reserved names are prefixed. Falls back to the platform's one
24
+ * fallback name (SAVED_FILENAME_FALLBACK) when nothing remains.
10
25
  */
11
26
  export declare function sanitizeFilename(filename: string): string;
@@ -1,27 +1,27 @@
1
+ import { isResourceId } from './app-sdk/ids.js';
1
2
  import { SparkVaultValidationError } from './errors.js';
2
- export function isSafeId(id) {
3
- if (!id || typeof id !== 'string')
4
- return false;
5
- if (id.includes('/') || id.includes('\\') || id.includes('..') || id.includes('\0'))
6
- return false;
7
- if (id.length < 8 || id.length > 128)
8
- return false;
9
- return /^[a-zA-Z0-9_-]+$/.test(id);
3
+ import { SAVED_FILENAME_FALLBACK, toStorableFilename } from './app-sdk/filename.js';
4
+ /** Whether a value is a well-formed SparkVault resource id (the platform's one rule). */
5
+ export { isResourceId as isSafeId };
6
+ /**
7
+ * Refuse a value that is not a SparkVault resource id before it names a route.
8
+ *
9
+ * @param label - How the message names the id, e.g. 'spark ID'.
10
+ * @param field - The argument's name, reported in the error details.
11
+ */
12
+ export function validateResourceId(value, label, field) {
13
+ if (!isResourceId(value)) {
14
+ throw new SparkVaultValidationError(`Invalid ${label} format`, { [field]: value });
15
+ }
10
16
  }
11
17
  export function validateVaultId(vaultId) {
12
- if (!isSafeId(vaultId)) {
13
- throw new SparkVaultValidationError('Invalid vault ID format', { vaultId });
14
- }
18
+ validateResourceId(vaultId, 'vault ID', 'vaultId');
15
19
  }
16
20
  export function validateIngotId(ingotId) {
17
- if (!isSafeId(ingotId)) {
18
- throw new SparkVaultValidationError('Invalid ingot ID format', { ingotId });
19
- }
21
+ validateResourceId(ingotId, 'ingot ID', 'ingotId');
20
22
  }
21
23
  export function validateFolderId(folderId) {
22
- if (!folderId || typeof folderId !== 'string' || !folderId.startsWith('fld_') || !isSafeId(folderId)) {
23
- throw new SparkVaultValidationError('Invalid folder ID format', { folderId });
24
- }
24
+ validateResourceId(folderId, 'folder ID', 'folderId');
25
25
  }
26
26
  /** Windows reserved filenames that cannot be used. */
27
27
  const WINDOWS_RESERVED_NAMES = new Set([
@@ -30,23 +30,25 @@ const WINDOWS_RESERVED_NAMES = new Set([
30
30
  'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9',
31
31
  ]);
32
32
  /**
33
- * Sanitize a filename to prevent path traversal and other security issues:
34
- * removes null bytes and control characters, strips path traversal sequences,
35
- * replaces directory separators, strips leading dots (hidden files), and
36
- * prefixes Windows reserved names. Falls back to 'file' when nothing remains.
33
+ * The file name to store or save text under, by the platform's one file-name
34
+ * rule (@sparkvault/app-sdk/filename, mirrored into ./app-sdk/filename.js):
35
+ * path separators, control characters and the bidi controls that disguise an
36
+ * extension (`invoice<U+202E>fdp.exe` shows as `invoiceexe.pdf`) become `_`,
37
+ * and so do the characters SparkVault refuses in a name (: * ? " < > |), so a
38
+ * name derived from a note's title uploads. With every separator gone no name
39
+ * can climb a directory, so a `..` inside a name is kept. On top of the rule,
40
+ * for the device's file system: leading dots are stripped (a hidden file) and
41
+ * Windows reserved names are prefixed. Falls back to the platform's one
42
+ * fallback name (SAVED_FILENAME_FALLBACK) when nothing remains.
37
43
  */
38
44
  export function sanitizeFilename(filename) {
39
- let sanitized = filename
40
- .replace(/\0/g, '')
41
- .replace(/[\x00-\x1f\x7f]/g, '')
42
- .replace(/\.\./g, '')
43
- .replace(/[\/\\]/g, '_')
45
+ let sanitized = toStorableFilename(filename)
44
46
  .replace(/^\.+/, '')
45
47
  .trim();
46
48
  const baseName = sanitized.split('.')[0].toUpperCase();
47
49
  if (WINDOWS_RESERVED_NAMES.has(baseName)) {
48
50
  sanitized = `_${sanitized}`;
49
51
  }
50
- return sanitized || 'file';
52
+ return sanitized || SAVED_FILENAME_FALLBACK;
51
53
  }
52
54
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClG,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,yBAAyB,CAAC,yBAAyB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,yBAAyB,CAAC,yBAAyB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrG,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IAC1B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACtE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CACvE,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,SAAS,GAAG,QAAQ;SACrB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,IAAI,EAAE,CAAC;IAEV,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,IAAI,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,SAAS,IAAI,MAAM,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEpF,yFAAyF;AACzF,OAAO,EAAE,YAAY,IAAI,QAAQ,EAAE,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,KAAa,EAAE,KAAa;IAC7E,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,yBAAyB,CAAC,WAAW,KAAK,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAED,sDAAsD;AACtD,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IAC1B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACtE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CACvE,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC;SACzC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,IAAI,EAAE,CAAC;IAEV,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,IAAI,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,SAAS,IAAI,uBAAuB,CAAC;AAC9C,CAAC"}
package/dist/vaults.d.ts CHANGED
@@ -1,49 +1,5 @@
1
1
  import type { MobileHttpClient } from './http.js';
2
- import type { CreateVaultRequest, CreateVaultResponse, ListVaultsResponse, UnsealVaultRequest, UnsealVaultResponse, UpdateVaultRequest, UpdateVaultResponse, Vault } from './types.js';
3
- export interface SharingConfig {
4
- vault_id: string;
5
- public_sharing_enabled: boolean;
6
- all_ingots_public: boolean;
7
- session_length_seconds: number | null;
8
- enabled_at: number | null;
9
- }
10
- export interface UploadConfig {
11
- vault_id: string;
12
- upload_portal_enabled: boolean;
13
- upload_portal_enabled_at: number | null;
14
- upload_widget_enabled: boolean;
15
- upload_widget_enabled_at: number | null;
16
- max_size_bytes: number | null;
17
- notification_email: string | null;
18
- portal_url?: string;
19
- }
20
- export interface UploadPortalEnabled {
21
- vault_id: string;
22
- upload_portal_enabled: true;
23
- enabled_at: number;
24
- portal_url: string;
25
- }
26
- export interface UploadWidgetEnabled {
27
- vault_id: string;
28
- upload_widget_enabled: true;
29
- enabled_at: number;
30
- }
31
- export interface UploadPortalDisabled {
32
- vault_id: string;
33
- upload_portal_enabled: false;
34
- disabled_at: number;
35
- }
36
- export interface UploadWidgetDisabled {
37
- vault_id: string;
38
- upload_widget_enabled: false;
39
- disabled_at: number;
40
- }
41
- export interface UploadConfigUpdate {
42
- vault_id: string;
43
- max_size_bytes: number;
44
- notification_email: string | null;
45
- updated_at: number;
46
- }
2
+ import type { AccessLogRetention, CreateVaultRequest, CreateVaultResponse, DisableVaultSharingResponse, EnableVaultSharingResponse, ListVaultsResponse, UnsealVaultRequest, UnsealVaultResponse, UpdateAccessLogRetentionResponse, UpdateVaultRequest, UpdateVaultResponse, UpdateVaultSharingResponse, UploadConfig, UploadConfigUpdate, UploadPortalDisabled, UploadPortalEnabled, UploadWidgetDisabled, UploadWidgetEnabled, Vault, VaultSharingConfig, VaultSharingOptions } from './types.js';
47
3
  export declare class MobileVaultsClient {
48
4
  private readonly http;
49
5
  constructor(http: MobileHttpClient);
@@ -53,6 +9,15 @@ export declare class MobileVaultsClient {
53
9
  limit?: number;
54
10
  cursor?: string;
55
11
  }): Promise<ListVaultsResponse>;
12
+ /**
13
+ * Every vault on the account, newest first. Follows next_cursor at the
14
+ * largest page size until the server reports no more — a page the server
15
+ * filtered down to nothing still carries a cursor. A failed page fails the
16
+ * listing: a vault picker must never show a silently partial account.
17
+ */
18
+ listAll(options?: {
19
+ status?: 'sealed' | 'unsealed';
20
+ }): Promise<Vault[]>;
56
21
  get(vaultId: string): Promise<Vault>;
57
22
  update(vaultId: string, request: UpdateVaultRequest): Promise<UpdateVaultResponse>;
58
23
  /**
@@ -62,48 +27,34 @@ export declare class MobileVaultsClient {
62
27
  * The name is sent base64(UTF-8) as `X-Confirm-Name-B64` so that vaults named
63
28
  * with any Unicode (emoji, CJK, the U+202F in macOS-style names) are
64
29
  * deletable — a raw header value throws before the request is sent for
65
- * non-latin1 characters. The legacy raw header is included only when the name
66
- * is latin1-safe, for older API servers.
30
+ * non-latin1 characters.
67
31
  */
68
32
  delete(vaultId: string, name: string): Promise<void>;
69
33
  unseal(vaultId: string, request: UnsealVaultRequest): Promise<UnsealVaultResponse>;
34
+ /**
35
+ * Seal the vault: end every session of it, so every VAT minted for it stops
36
+ * working, whoever holds it. To end only the caller's own session, use
37
+ * `endSession`.
38
+ */
70
39
  seal(vaultId: string): Promise<void>;
71
- getSharingConfig(vaultId: string): Promise<SharingConfig>;
72
- enableSharing(vaultId: string, vmk: string, options?: {
73
- all_ingots_public?: boolean;
74
- session_length_seconds?: number;
75
- }): Promise<{
76
- vault_id: string;
77
- public_sharing_enabled: boolean;
78
- all_ingots_public: boolean;
79
- session_length_seconds: number;
80
- enabled_at: number;
81
- }>;
82
- disableSharing(vaultId: string): Promise<{
83
- vault_id: string;
84
- public_sharing_enabled: false;
85
- disabled_at: number;
86
- shares_revoked: number;
87
- }>;
88
- updateSharingConfig(vaultId: string, config: {
89
- all_ingots_public?: boolean;
90
- session_length_seconds?: number;
91
- }): Promise<{
92
- vault_id: string;
93
- public_sharing_enabled: boolean;
94
- all_ingots_public: boolean;
95
- session_length_seconds: number;
96
- updated_at: number;
97
- }>;
98
- getAccessLogRetention(vaultId: string): Promise<{
99
- vault_id: string;
100
- access_log_retention_seconds: number;
101
- }>;
102
- updateAccessLogRetention(vaultId: string, retentionSeconds: number): Promise<{
103
- vault_id: string;
104
- access_log_retention_seconds: number;
105
- updated_at: number;
106
- }>;
40
+ /**
41
+ * End the session `vat` names, and no other session of the vault: every
42
+ * other holder keeps theirs. A VAT the server already refuses (an
43
+ * `isVatExpiredError` or a `vatRefusalReason` of VAT_INVALID) names a
44
+ * session that is already over.
45
+ */
46
+ endSession(vaultId: string, vat: string): Promise<void>;
47
+ getSharingConfig(vaultId: string): Promise<VaultSharingConfig>;
48
+ enableSharing(vaultId: string, vmk: string, options?: VaultSharingOptions): Promise<EnableVaultSharingResponse>;
49
+ disableSharing(vaultId: string): Promise<DisableVaultSharingResponse>;
50
+ /**
51
+ * Update the vault's sharing policy. Making every ingot public publishes
52
+ * each file to anyone holding its URL, so the API accepts
53
+ * `all_ingots_public: true` only with a read-write VAT for this vault.
54
+ */
55
+ updateSharingConfig(vaultId: string, config: VaultSharingOptions, vat?: string): Promise<UpdateVaultSharingResponse>;
56
+ getAccessLogRetention(vaultId: string): Promise<AccessLogRetention>;
57
+ updateAccessLogRetention(vaultId: string, retentionSeconds: number): Promise<UpdateAccessLogRetentionResponse>;
107
58
  getUploadConfig(vaultId: string): Promise<UploadConfig>;
108
59
  enableUploadPortal(vaultId: string, vmk: string): Promise<UploadPortalEnabled>;
109
60
  disableUploadPortal(vaultId: string): Promise<UploadPortalDisabled>;
package/dist/vaults.js CHANGED
@@ -1,41 +1,46 @@
1
1
  import { validateVaultId } from './validation.js';
2
2
  import { base64EncodeUtf8 } from './encoding.js';
3
- /** A string every char of which fits in a single header byte (latin1). */
4
- function isLatin1(value) {
5
- for (let i = 0; i < value.length; i++) {
6
- if (value.charCodeAt(i) > 0xff)
7
- return false;
8
- }
9
- return true;
10
- }
3
+ import { apiPath } from './request-path.js';
4
+ /** GET /v1/vaults' largest page (apps/api vaults/list.js maxLimit). */
5
+ const VAULT_LIST_PAGE_LIMIT = 500;
11
6
  export class MobileVaultsClient {
12
7
  constructor(http) {
13
8
  this.http = http;
14
9
  }
15
10
  async create(request) {
16
- const response = await this.http.post('/vaults', request);
11
+ const response = await this.http.post(apiPath `/vaults`, request);
17
12
  return response.data;
18
13
  }
19
14
  async list(options) {
20
- const params = new URLSearchParams();
21
- if (options?.status)
22
- params.append('status', options.status);
23
- if (options?.limit)
24
- params.append('limit', options.limit.toString());
25
- if (options?.cursor)
26
- params.append('cursor', options.cursor);
27
- const query = params.toString();
28
- const response = await this.http.get(query ? `/vaults?${query}` : '/vaults');
15
+ const response = await this.http.get(apiPath `/vaults`, {
16
+ query: { status: options?.status, limit: options?.limit || undefined, cursor: options?.cursor },
17
+ });
29
18
  return response.data;
30
19
  }
20
+ /**
21
+ * Every vault on the account, newest first. Follows next_cursor at the
22
+ * largest page size until the server reports no more — a page the server
23
+ * filtered down to nothing still carries a cursor. A failed page fails the
24
+ * listing: a vault picker must never show a silently partial account.
25
+ */
26
+ async listAll(options) {
27
+ const vaults = [];
28
+ let cursor;
29
+ do {
30
+ const page = await this.list({ ...options, limit: VAULT_LIST_PAGE_LIMIT, cursor });
31
+ vaults.push(...page.vaults);
32
+ cursor = page.has_more ? page.next_cursor : undefined;
33
+ } while (cursor);
34
+ return vaults;
35
+ }
31
36
  async get(vaultId) {
32
37
  validateVaultId(vaultId);
33
- const response = await this.http.get(`/vaults/${vaultId}`);
38
+ const response = await this.http.get(apiPath `/vaults/${vaultId}`);
34
39
  return response.data;
35
40
  }
36
41
  async update(vaultId, request) {
37
42
  validateVaultId(vaultId);
38
- const response = await this.http.put(`/vaults/${vaultId}`, request);
43
+ const response = await this.http.put(apiPath `/vaults/${vaultId}`, request);
39
44
  return response.data;
40
45
  }
41
46
  /**
@@ -45,39 +50,49 @@ export class MobileVaultsClient {
45
50
  * The name is sent base64(UTF-8) as `X-Confirm-Name-B64` so that vaults named
46
51
  * with any Unicode (emoji, CJK, the U+202F in macOS-style names) are
47
52
  * deletable — a raw header value throws before the request is sent for
48
- * non-latin1 characters. The legacy raw header is included only when the name
49
- * is latin1-safe, for older API servers.
53
+ * non-latin1 characters.
50
54
  */
51
55
  async delete(vaultId, name) {
52
56
  validateVaultId(vaultId);
53
57
  if (!name) {
54
58
  throw new Error('Vault name is required to confirm deletion');
55
59
  }
56
- const headers = {
57
- 'X-Confirm-Name-B64': base64EncodeUtf8(name),
58
- };
59
- if (isLatin1(name)) {
60
- headers['X-Confirm-Name'] = name;
61
- }
62
- await this.http.delete(`/vaults/${vaultId}`, { headers });
60
+ await this.http.delete(apiPath `/vaults/${vaultId}`, {
61
+ headers: { 'X-Confirm-Name-B64': base64EncodeUtf8(name) },
62
+ });
63
63
  }
64
64
  async unseal(vaultId, request) {
65
65
  validateVaultId(vaultId);
66
- const response = await this.http.post(`/vaults/${vaultId}/unseal`, request);
66
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/unseal`, request);
67
67
  return response.data;
68
68
  }
69
+ /**
70
+ * Seal the vault: end every session of it, so every VAT minted for it stops
71
+ * working, whoever holds it. To end only the caller's own session, use
72
+ * `endSession`.
73
+ */
69
74
  async seal(vaultId) {
70
75
  validateVaultId(vaultId);
71
- await this.http.post(`/vaults/${vaultId}/seal`);
76
+ await this.http.post(apiPath `/vaults/${vaultId}/seal`);
77
+ }
78
+ /**
79
+ * End the session `vat` names, and no other session of the vault: every
80
+ * other holder keeps theirs. A VAT the server already refuses (an
81
+ * `isVatExpiredError` or a `vatRefusalReason` of VAT_INVALID) names a
82
+ * session that is already over.
83
+ */
84
+ async endSession(vaultId, vat) {
85
+ validateVaultId(vaultId);
86
+ await this.http.delete(apiPath `/vaults/${vaultId}/session`, { vat });
72
87
  }
73
88
  async getSharingConfig(vaultId) {
74
89
  validateVaultId(vaultId);
75
- const response = await this.http.get(`/vaults/${vaultId}/sharing`);
90
+ const response = await this.http.get(apiPath `/vaults/${vaultId}/sharing`);
76
91
  return response.data;
77
92
  }
78
93
  async enableSharing(vaultId, vmk, options) {
79
94
  validateVaultId(vaultId);
80
- const response = await this.http.post(`/vaults/${vaultId}/sharing/enable`, {
95
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/sharing/enable`, {
81
96
  vmk,
82
97
  all_ingots_public: options?.all_ingots_public,
83
98
  session_length_seconds: options?.session_length_seconds,
@@ -86,58 +101,63 @@ export class MobileVaultsClient {
86
101
  }
87
102
  async disableSharing(vaultId) {
88
103
  validateVaultId(vaultId);
89
- const response = await this.http.post(`/vaults/${vaultId}/sharing/disable`);
104
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/sharing/disable`);
90
105
  return response.data;
91
106
  }
92
- async updateSharingConfig(vaultId, config) {
107
+ /**
108
+ * Update the vault's sharing policy. Making every ingot public publishes
109
+ * each file to anyone holding its URL, so the API accepts
110
+ * `all_ingots_public: true` only with a read-write VAT for this vault.
111
+ */
112
+ async updateSharingConfig(vaultId, config, vat) {
93
113
  validateVaultId(vaultId);
94
- const response = await this.http.put(`/vaults/${vaultId}/sharing`, config);
114
+ const response = await this.http.put(apiPath `/vaults/${vaultId}/sharing`, config, { vat });
95
115
  return response.data;
96
116
  }
97
117
  async getAccessLogRetention(vaultId) {
98
118
  validateVaultId(vaultId);
99
- const response = await this.http.get(`/vaults/${vaultId}/access-log-retention`);
119
+ const response = await this.http.get(apiPath `/vaults/${vaultId}/access-log-retention`);
100
120
  return response.data;
101
121
  }
102
122
  async updateAccessLogRetention(vaultId, retentionSeconds) {
103
123
  validateVaultId(vaultId);
104
- const response = await this.http.put(`/vaults/${vaultId}/access-log-retention`, {
124
+ const response = await this.http.put(apiPath `/vaults/${vaultId}/access-log-retention`, {
105
125
  access_log_retention_seconds: retentionSeconds,
106
126
  });
107
127
  return response.data;
108
128
  }
109
129
  async getUploadConfig(vaultId) {
110
130
  validateVaultId(vaultId);
111
- const response = await this.http.get(`/vaults/${vaultId}/upload`);
131
+ const response = await this.http.get(apiPath `/vaults/${vaultId}/upload`);
112
132
  return response.data;
113
133
  }
114
134
  async enableUploadPortal(vaultId, vmk) {
115
135
  validateVaultId(vaultId);
116
- const response = await this.http.post(`/vaults/${vaultId}/upload/portal/enable`, {
136
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/upload/portal/enable`, {
117
137
  vmk,
118
138
  });
119
139
  return response.data;
120
140
  }
121
141
  async disableUploadPortal(vaultId) {
122
142
  validateVaultId(vaultId);
123
- const response = await this.http.post(`/vaults/${vaultId}/upload/portal/disable`);
143
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/upload/portal/disable`);
124
144
  return response.data;
125
145
  }
126
146
  async enableUploadWidget(vaultId, vmk) {
127
147
  validateVaultId(vaultId);
128
- const response = await this.http.post(`/vaults/${vaultId}/upload/widget/enable`, {
148
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/upload/widget/enable`, {
129
149
  vmk,
130
150
  });
131
151
  return response.data;
132
152
  }
133
153
  async disableUploadWidget(vaultId) {
134
154
  validateVaultId(vaultId);
135
- const response = await this.http.post(`/vaults/${vaultId}/upload/widget/disable`);
155
+ const response = await this.http.post(apiPath `/vaults/${vaultId}/upload/widget/disable`);
136
156
  return response.data;
137
157
  }
138
158
  async updateUploadConfig(vaultId, config) {
139
159
  validateVaultId(vaultId);
140
- const response = await this.http.put(`/vaults/${vaultId}/upload`, config);
160
+ const response = await this.http.put(apiPath `/vaults/${vaultId}/upload`, config);
141
161
  return response.data;
142
162
  }
143
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vaults.js","sourceRoot":"","sources":["../src/vaults.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vaults.js","sourceRoot":"","sources":["../src/vaults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Vault and folder wire-contract assertions — COMPILE-TIME ONLY.
3
+ *
4
+ * These types have no runtime, so a unit test can never catch them drifting from
5
+ * the server: the transpiler strips them and every assertion passes. `tsc
6
+ * --noEmit` (`pnpm typecheck`) is the gate instead. It is deliberately NOT a
7
+ * `*.test.ts`, which tsconfig excludes.
8
+ *
9
+ * Mirrored server sources: apps/api/src/folders/list.js (listFolders answers
10
+ * `{ folders }`, the whole list and nothing else) and apps/api/src/vaults/list.js
11
+ * (one page: `{ vaults, count, has_more, next_cursor? }`).
12
+ */
13
+ import type { ListFoldersResponse, ListVaultsResponse } from './types.js';
14
+ /** Fails to compile unless `T` resolves to exactly `true`. */
15
+ type Assert<T extends true> = T;
16
+ /** Invariant type equality: the SAME type, not merely mutually assignable. */
17
+ type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
18
+ export type VaultsWireContract = [
19
+ Assert<Equals<keyof ListFoldersResponse, 'folders'>>,
20
+ Assert<Equals<keyof ListVaultsResponse, 'vaults' | 'count' | 'has_more' | 'next_cursor'>>
21
+ ];
22
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Vault and folder wire-contract assertions — COMPILE-TIME ONLY.
3
+ *
4
+ * These types have no runtime, so a unit test can never catch them drifting from
5
+ * the server: the transpiler strips them and every assertion passes. `tsc
6
+ * --noEmit` (`pnpm typecheck`) is the gate instead. It is deliberately NOT a
7
+ * `*.test.ts`, which tsconfig excludes.
8
+ *
9
+ * Mirrored server sources: apps/api/src/folders/list.js (listFolders answers
10
+ * `{ folders }`, the whole list and nothing else) and apps/api/src/vaults/list.js
11
+ * (one page: `{ vaults, count, has_more, next_cursor? }`).
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=vaults.test-d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vaults.test-d.js","sourceRoot":"","sources":["../src/vaults.test-d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}