@sparkvault/sdk-mobile 6.0.2 → 7.0.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.
Files changed (156) 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/transfer-retry.d.ts +298 -0
  36. package/dist/app-sdk/transfer-retry.js +535 -0
  37. package/dist/app-sdk/transfer-retry.js.map +1 -0
  38. package/dist/app-sdk/transient.d.ts +23 -0
  39. package/dist/app-sdk/transient.js +29 -0
  40. package/dist/app-sdk/transient.js.map +1 -0
  41. package/dist/app-sdk/upload-publication.d.ts +81 -0
  42. package/dist/app-sdk/upload-publication.js +93 -0
  43. package/dist/app-sdk/upload-publication.js.map +1 -0
  44. package/dist/app-sdk/vat-refusal.d.ts +66 -0
  45. package/dist/app-sdk/vat-refusal.js +69 -0
  46. package/dist/app-sdk/vat-refusal.js.map +1 -0
  47. package/dist/billing.d.ts +9 -17
  48. package/dist/billing.js +14 -17
  49. package/dist/billing.js.map +1 -1
  50. package/dist/config.d.ts +33 -1
  51. package/dist/config.js +23 -17
  52. package/dist/config.js.map +1 -1
  53. package/dist/encoding.d.ts +30 -4
  54. package/dist/encoding.js +89 -83
  55. package/dist/encoding.js.map +1 -1
  56. package/dist/entropy.d.ts +25 -4
  57. package/dist/entropy.js +62 -15
  58. package/dist/entropy.js.map +1 -1
  59. package/dist/entropy.test-d.d.ts +40 -0
  60. package/dist/entropy.test-d.js +12 -0
  61. package/dist/entropy.test-d.js.map +1 -0
  62. package/dist/errors.d.ts +105 -21
  63. package/dist/errors.js +74 -28
  64. package/dist/errors.js.map +1 -1
  65. package/dist/folders.js +8 -7
  66. package/dist/folders.js.map +1 -1
  67. package/dist/http.d.ts +57 -15
  68. package/dist/http.js +125 -138
  69. package/dist/http.js.map +1 -1
  70. package/dist/identity-dialog.js +4 -30
  71. package/dist/identity-dialog.js.map +1 -1
  72. package/dist/identity-input.d.ts +39 -0
  73. package/dist/identity-input.js +59 -0
  74. package/dist/identity-input.js.map +1 -0
  75. package/dist/index.d.ts +8 -7
  76. package/dist/index.js +5 -4
  77. package/dist/index.js.map +1 -1
  78. package/dist/ingots.d.ts +77 -32
  79. package/dist/ingots.js +152 -136
  80. package/dist/ingots.js.map +1 -1
  81. package/dist/mutex.d.ts +1 -2
  82. package/dist/mutex.js +0 -6
  83. package/dist/mutex.js.map +1 -1
  84. package/dist/notify.d.ts +7 -2
  85. package/dist/notify.js +12 -15
  86. package/dist/notify.js.map +1 -1
  87. package/dist/notify.test-d.d.ts +3 -2
  88. package/dist/notify.test-d.js +1 -1
  89. package/dist/products/identity.d.ts +5 -0
  90. package/dist/products/identity.js +40 -35
  91. package/dist/products/identity.js.map +1 -1
  92. package/dist/request-path.d.ts +32 -0
  93. package/dist/request-path.js +35 -0
  94. package/dist/request-path.js.map +1 -0
  95. package/dist/sparks.js +16 -15
  96. package/dist/sparks.js.map +1 -1
  97. package/dist/tus.d.ts +198 -16
  98. package/dist/tus.js +816 -327
  99. package/dist/tus.js.map +1 -1
  100. package/dist/types.d.ts +183 -23
  101. package/dist/users.d.ts +12 -5
  102. package/dist/users.js +27 -19
  103. package/dist/users.js.map +1 -1
  104. package/dist/validation.d.ts +20 -5
  105. package/dist/validation.js +29 -27
  106. package/dist/validation.js.map +1 -1
  107. package/dist/vaults.d.ts +34 -83
  108. package/dist/vaults.js +64 -44
  109. package/dist/vaults.js.map +1 -1
  110. package/dist/vaults.test-d.d.ts +22 -0
  111. package/dist/vaults.test-d.js +14 -0
  112. package/dist/vaults.test-d.js.map +1 -0
  113. package/package.json +4 -2
  114. package/src/account.ts +16 -11
  115. package/src/app-sdk/email-address.js +94 -0
  116. package/src/app-sdk/encoding.js +250 -0
  117. package/src/app-sdk/entropy-contract.js +56 -0
  118. package/src/app-sdk/filename.js +174 -0
  119. package/src/app-sdk/forge-url.js +224 -0
  120. package/src/app-sdk/ids.js +71 -0
  121. package/src/app-sdk/ingot-access-log.js +51 -0
  122. package/src/app-sdk/phone.js +139 -0
  123. package/src/app-sdk/platform-domains.js +99 -0
  124. package/src/app-sdk/request-path.js +81 -0
  125. package/src/app-sdk/transfer-retry.js +563 -0
  126. package/src/app-sdk/transient.js +30 -0
  127. package/src/app-sdk/upload-publication.js +102 -0
  128. package/src/app-sdk/vat-refusal.js +74 -0
  129. package/src/billing.ts +16 -25
  130. package/src/config.ts +56 -23
  131. package/src/encoding.ts +91 -103
  132. package/src/entropy.test-d.ts +47 -0
  133. package/src/entropy.ts +86 -20
  134. package/src/errors.ts +135 -38
  135. package/src/folders.ts +8 -7
  136. package/src/http.ts +145 -150
  137. package/src/identity-dialog.tsx +4 -37
  138. package/src/identity-input.ts +70 -0
  139. package/src/index.ts +13 -3
  140. package/src/ingots.ts +225 -180
  141. package/src/mutex.ts +1 -8
  142. package/src/notify.test-d.ts +3 -1
  143. package/src/notify.ts +19 -17
  144. package/src/products/identity.ts +45 -39
  145. package/src/request-path.ts +45 -0
  146. package/src/sparks.ts +16 -13
  147. package/src/tus.ts +1054 -408
  148. package/src/types.ts +181 -23
  149. package/src/users.ts +27 -17
  150. package/src/validation.ts +30 -24
  151. package/src/vaults.test-d.ts +29 -0
  152. package/src/vaults.ts +87 -153
  153. package/dist/platform-domains.generated.d.ts +0 -2
  154. package/dist/platform-domains.generated.js +0 -16
  155. package/dist/platform-domains.generated.js.map +0 -1
  156. package/src/platform-domains.generated.ts +0 -17
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The ledger reference of an upload's transfer charge,
3
+ * `forge_ingot_transfer_upload_<first 24 ISTK chars>`: every charge of one
4
+ * upload carries it — Core's activation, Core's charge of an upload that never
5
+ * publishes, Forge's cancel — so whichever lands first is the upload's one
6
+ * ledger row and the others are duplicates.
7
+ *
8
+ * @param {string} istk - The upload's ISTK, as its session carries it
9
+ * @returns {string}
10
+ * @throws {TypeError} When the ISTK is not a string of at least
11
+ * TRANSFER_REFERENCE_ISTK_CHARS characters
12
+ */
13
+ export function uploadTransferReference(istk: string): string;
14
+ /**
15
+ * The upload publication contract between Forge and Core's activation.
16
+ *
17
+ * Forge stamps UPLOAD_PUBLICATION_PROTOCOL on every upload session it creates
18
+ * and on the final state it hands Core's activation (POST
19
+ * /v1/vaults/:vault_id/ingots/:ingot_id/activate); activation refuses any
20
+ * other version. The two services deploy separately, so a change to what
21
+ * either side sends or expects moves this number: a session or a finalize
22
+ * from the other side's contract then fails closed ("restart the upload")
23
+ * instead of publishing under a contract the other side does not hold.
24
+ *
25
+ * Version 2: an upload's own metadata (content type, original file name,
26
+ * uploader, content HMAC) travels on its upload token and its session, and
27
+ * activation publishes it from the session; the final state Forge sends
28
+ * carries only the storage facts Forge owns.
29
+ *
30
+ * Isomorphic: no Node imports.
31
+ */
32
+ export const UPLOAD_PUBLICATION_PROTOCOL: 2;
33
+ /**
34
+ * An upload's id as both services spell it: `tus_` and the 32 lowercase hex
35
+ * digits of 16 random bytes. An encrypt token that names one (`upload_id`)
36
+ * was staged by Core under it, and Forge keys the upload's session, its chunk
37
+ * prefix and its VAK wrapping by it, so Core finds and settles the upload by
38
+ * the session's id.
39
+ */
40
+ export const UPLOAD_ID_PATTERN: RegExp;
41
+ /**
42
+ * How much of an ISTK names a transfer's charge on the usage ledger: enough to
43
+ * be unique to the token, never the whole bearer credential.
44
+ */
45
+ export const TRANSFER_REFERENCE_ISTK_CHARS: 24;
46
+ /**
47
+ * The codes Core's activation refuses an upload with, which Forge's refusal
48
+ * map reads (the status is Core's):
49
+ * - UPLOAD_CONTRACT_MISMATCH (409): a finalize or session from another
50
+ * publication contract than Core's, a mixed deployment that converges — the
51
+ * upload is kept and its finalize tried again.
52
+ * - UPLOAD_PROTOCOL_RETIRED (410): a session from a contract Core no longer
53
+ * publishes, which never can be.
54
+ * - UPLOAD_SUPERSEDED (410): a session a later staging of its ingot
55
+ * superseded, which never can be.
56
+ * - UPLOAD_POOL_FULL (402): an upload the owner's storage pool cannot take at
57
+ * publication, which is final.
58
+ */
59
+ export const UPLOAD_REFUSAL_CODES: Readonly<{
60
+ UPLOAD_CONTRACT_MISMATCH: "UPLOAD_CONTRACT_MISMATCH";
61
+ UPLOAD_PROTOCOL_RETIRED: "UPLOAD_PROTOCOL_RETIRED";
62
+ UPLOAD_SUPERSEDED: "UPLOAD_SUPERSEDED";
63
+ UPLOAD_POOL_FULL: "UPLOAD_POOL_FULL";
64
+ }>;
65
+ /**
66
+ * The refusals of Core's that a new upload of the same file cannot remedy:
67
+ * the owner's storage pool cannot take it (UPLOAD_POOL_FULL), or a later
68
+ * upload of its ingot replaced it (UPLOAD_SUPERSEDED). Any other code Core
69
+ * ends an upload with ends its session alone, which a new upload starts
70
+ * over. Every client reads a terminal answer's code by it
71
+ * (transfer-retry.js): one of these is a refusal it reports in Core's words,
72
+ * any other a gone session.
73
+ */
74
+ export const UPLOAD_FINAL_REFUSAL_CODES: readonly ("UPLOAD_SUPERSEDED" | "UPLOAD_POOL_FULL")[];
75
+ /**
76
+ * The response header that names the code Core refused an upload with for
77
+ * good: Forge sends it on every terminal answer to a tus request, a HEAD's
78
+ * (which has no body) included, so a client tells an upload the owner's pool
79
+ * cannot take from one a later upload superseded without reading a body.
80
+ */
81
+ export const UPLOAD_REFUSAL_HEADER: "X-Upload-Refusal";
@@ -0,0 +1,93 @@
1
+ // GENERATED FILE — do not edit by hand.
2
+ // Source of truth: packages/app-sdk/src/upload-publication.js
3
+ // Regenerate with: pnpm --filter @sparkvault/sdk-mobile build
4
+ /**
5
+ * The upload publication contract between Forge and Core's activation.
6
+ *
7
+ * Forge stamps UPLOAD_PUBLICATION_PROTOCOL on every upload session it creates
8
+ * and on the final state it hands Core's activation (POST
9
+ * /v1/vaults/:vault_id/ingots/:ingot_id/activate); activation refuses any
10
+ * other version. The two services deploy separately, so a change to what
11
+ * either side sends or expects moves this number: a session or a finalize
12
+ * from the other side's contract then fails closed ("restart the upload")
13
+ * instead of publishing under a contract the other side does not hold.
14
+ *
15
+ * Version 2: an upload's own metadata (content type, original file name,
16
+ * uploader, content HMAC) travels on its upload token and its session, and
17
+ * activation publishes it from the session; the final state Forge sends
18
+ * carries only the storage facts Forge owns.
19
+ *
20
+ * Isomorphic: no Node imports.
21
+ */
22
+ export const UPLOAD_PUBLICATION_PROTOCOL = 2;
23
+ /**
24
+ * An upload's id as both services spell it: `tus_` and the 32 lowercase hex
25
+ * digits of 16 random bytes. An encrypt token that names one (`upload_id`)
26
+ * was staged by Core under it, and Forge keys the upload's session, its chunk
27
+ * prefix and its VAK wrapping by it, so Core finds and settles the upload by
28
+ * the session's id.
29
+ */
30
+ export const UPLOAD_ID_PATTERN = /^tus_[0-9a-f]{32}$/;
31
+ /**
32
+ * How much of an ISTK names a transfer's charge on the usage ledger: enough to
33
+ * be unique to the token, never the whole bearer credential.
34
+ */
35
+ export const TRANSFER_REFERENCE_ISTK_CHARS = 24;
36
+ /**
37
+ * The ledger reference of an upload's transfer charge,
38
+ * `forge_ingot_transfer_upload_<first 24 ISTK chars>`: every charge of one
39
+ * upload carries it — Core's activation, Core's charge of an upload that never
40
+ * publishes, Forge's cancel — so whichever lands first is the upload's one
41
+ * ledger row and the others are duplicates.
42
+ *
43
+ * @param {string} istk - The upload's ISTK, as its session carries it
44
+ * @returns {string}
45
+ * @throws {TypeError} When the ISTK is not a string of at least
46
+ * TRANSFER_REFERENCE_ISTK_CHARS characters
47
+ */
48
+ export function uploadTransferReference(istk) {
49
+ if (typeof istk !== 'string' || istk.length < TRANSFER_REFERENCE_ISTK_CHARS) {
50
+ throw new TypeError(`An upload's transfer reference is named from its ISTK, a string of at least ${TRANSFER_REFERENCE_ISTK_CHARS} characters`);
51
+ }
52
+ return `forge_ingot_transfer_upload_${istk.slice(0, TRANSFER_REFERENCE_ISTK_CHARS)}`;
53
+ }
54
+ /**
55
+ * The codes Core's activation refuses an upload with, which Forge's refusal
56
+ * map reads (the status is Core's):
57
+ * - UPLOAD_CONTRACT_MISMATCH (409): a finalize or session from another
58
+ * publication contract than Core's, a mixed deployment that converges — the
59
+ * upload is kept and its finalize tried again.
60
+ * - UPLOAD_PROTOCOL_RETIRED (410): a session from a contract Core no longer
61
+ * publishes, which never can be.
62
+ * - UPLOAD_SUPERSEDED (410): a session a later staging of its ingot
63
+ * superseded, which never can be.
64
+ * - UPLOAD_POOL_FULL (402): an upload the owner's storage pool cannot take at
65
+ * publication, which is final.
66
+ */
67
+ export const UPLOAD_REFUSAL_CODES = Object.freeze({
68
+ UPLOAD_CONTRACT_MISMATCH: 'UPLOAD_CONTRACT_MISMATCH',
69
+ UPLOAD_PROTOCOL_RETIRED: 'UPLOAD_PROTOCOL_RETIRED',
70
+ UPLOAD_SUPERSEDED: 'UPLOAD_SUPERSEDED',
71
+ UPLOAD_POOL_FULL: 'UPLOAD_POOL_FULL'
72
+ });
73
+ /**
74
+ * The refusals of Core's that a new upload of the same file cannot remedy:
75
+ * the owner's storage pool cannot take it (UPLOAD_POOL_FULL), or a later
76
+ * upload of its ingot replaced it (UPLOAD_SUPERSEDED). Any other code Core
77
+ * ends an upload with ends its session alone, which a new upload starts
78
+ * over. Every client reads a terminal answer's code by it
79
+ * (transfer-retry.js): one of these is a refusal it reports in Core's words,
80
+ * any other a gone session.
81
+ */
82
+ export const UPLOAD_FINAL_REFUSAL_CODES = Object.freeze([
83
+ UPLOAD_REFUSAL_CODES.UPLOAD_POOL_FULL,
84
+ UPLOAD_REFUSAL_CODES.UPLOAD_SUPERSEDED
85
+ ]);
86
+ /**
87
+ * The response header that names the code Core refused an upload with for
88
+ * good: Forge sends it on every terminal answer to a tus request, a HEAD's
89
+ * (which has no body) included, so a client tells an upload the owner's pool
90
+ * cannot take from one a later upload superseded without reading a body.
91
+ */
92
+ export const UPLOAD_REFUSAL_HEADER = 'X-Upload-Refusal';
93
+ //# sourceMappingURL=upload-publication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-publication.js","sourceRoot":"","sources":["../../src/app-sdk/upload-publication.js"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,8DAA8D;AAC9D,8DAA8D;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAI;IAC1C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,6BAA6B,EAAE,CAAC;QAC5E,MAAM,IAAI,SAAS,CACjB,+EAA+E,6BAA6B,aAAa,CAC1H,CAAC;IACJ,CAAC;IACD,OAAO,+BAA+B,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,6BAA6B,CAAC,EAAE,CAAC;AACvF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IAChD,wBAAwB,EAAE,0BAA0B;IACpD,uBAAuB,EAAE,yBAAyB;IAClD,iBAAiB,EAAE,mBAAmB;IACtC,gBAAgB,EAAE,kBAAkB;CACrC,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC;IACtD,oBAAoB,CAAC,gBAAgB;IACrC,oBAAoB,CAAC,iBAAiB;CACvC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The VAT refusal a Core error answer names, or null when it is not one.
3
+ *
4
+ * @param {{ statusCode?: number, details?: { reason?: string } }} error - An
5
+ * error as parsed from a Core response (status plus the body's `details`)
6
+ * @returns {string|null} One of VAT_REFUSAL_REASONS, or null
7
+ */
8
+ export function vatRefusalReason(error: {
9
+ statusCode?: number;
10
+ details?: {
11
+ reason?: string;
12
+ };
13
+ }): string | null;
14
+ /**
15
+ * Whether a refusal says the token's vault session is over: an invalid or an
16
+ * expired token, which only a new unseal replaces, so a client forgets it. A
17
+ * read-only refusal leaves the session standing (the token still reads), and
18
+ * so does a refusal that names no VAT reason.
19
+ *
20
+ * @param {string|null} reason - What vatRefusalReason returned
21
+ * @returns {boolean}
22
+ */
23
+ export function endsVatSession(reason: string | null): boolean;
24
+ /**
25
+ * True when Core refused the request's login, not a Vault Access Token it
26
+ * carried: a 401 bearing Core's session code (AUTHENTICATION_ERROR, the
27
+ * mapped error's `upstreamCode`) that names no VAT refusal. Its token was
28
+ * refused, or its account is unavailable (details.reason ACCOUNT_UNAVAILABLE,
29
+ * ./refusal-reasons.js). A 401 for a credential in the request body (an
30
+ * unseal key) carries Core's credential code (UNAUTHORIZED) and is not one.
31
+ *
32
+ * @param {{ statusCode?: number, upstreamCode?: string|null, details?: { reason?: string } }} error -
33
+ * An error as parsed from a Core response (parseApiError)
34
+ * @returns {boolean}
35
+ */
36
+ export function isRefusedLogin(error: {
37
+ statusCode?: number;
38
+ upstreamCode?: string | null;
39
+ details?: {
40
+ reason?: string;
41
+ };
42
+ }): boolean;
43
+ /**
44
+ * Why Core refused a Vault Access Token (VAT): the `details.reason` every VAT
45
+ * refusal carries, and the one reading of it clients share.
46
+ *
47
+ * 401 VAT_INVALID no token, or a malformed, unknown or swept one, or one a
48
+ * since-revoked DVAK minted — unseal again
49
+ * 403 VAT_EXPIRED the token outlived its TTL — unseal again, retry as-is
50
+ * 403 VAT_READ_ONLY a View Only token on a write — no unseal fixes it
51
+ *
52
+ * A 403 with no reason is a token for another vault or account, which no
53
+ * unseal of this vault fixes; a 401 with no reason is the login itself, never
54
+ * the VAT. Browser-safe: no imports.
55
+ */
56
+ export const VAT_REFUSAL_REASONS: Readonly<{
57
+ INVALID: "VAT_INVALID";
58
+ EXPIRED: "VAT_EXPIRED";
59
+ READ_ONLY: "VAT_READ_ONLY";
60
+ }>;
61
+ /** The status each refusal is answered with. */
62
+ export const VAT_REFUSAL_STATUS: Readonly<{
63
+ VAT_INVALID: 401;
64
+ VAT_EXPIRED: 403;
65
+ VAT_READ_ONLY: 403;
66
+ }>;
@@ -0,0 +1,69 @@
1
+ // GENERATED FILE — do not edit by hand.
2
+ // Source of truth: packages/app-sdk/src/vat-refusal.js
3
+ // Regenerate with: pnpm --filter @sparkvault/sdk-mobile build
4
+ /**
5
+ * Why Core refused a Vault Access Token (VAT): the `details.reason` every VAT
6
+ * refusal carries, and the one reading of it clients share.
7
+ *
8
+ * 401 VAT_INVALID no token, or a malformed, unknown or swept one, or one a
9
+ * since-revoked DVAK minted — unseal again
10
+ * 403 VAT_EXPIRED the token outlived its TTL — unseal again, retry as-is
11
+ * 403 VAT_READ_ONLY a View Only token on a write — no unseal fixes it
12
+ *
13
+ * A 403 with no reason is a token for another vault or account, which no
14
+ * unseal of this vault fixes; a 401 with no reason is the login itself, never
15
+ * the VAT. Browser-safe: no imports.
16
+ */
17
+ export const VAT_REFUSAL_REASONS = Object.freeze({
18
+ INVALID: 'VAT_INVALID',
19
+ EXPIRED: 'VAT_EXPIRED',
20
+ READ_ONLY: 'VAT_READ_ONLY'
21
+ });
22
+ /** The status each refusal is answered with. */
23
+ export const VAT_REFUSAL_STATUS = Object.freeze({
24
+ [VAT_REFUSAL_REASONS.INVALID]: 401,
25
+ [VAT_REFUSAL_REASONS.EXPIRED]: 403,
26
+ [VAT_REFUSAL_REASONS.READ_ONLY]: 403
27
+ });
28
+ /**
29
+ * The VAT refusal a Core error answer names, or null when it is not one.
30
+ *
31
+ * @param {{ statusCode?: number, details?: { reason?: string } }} error - An
32
+ * error as parsed from a Core response (status plus the body's `details`)
33
+ * @returns {string|null} One of VAT_REFUSAL_REASONS, or null
34
+ */
35
+ export function vatRefusalReason(error) {
36
+ const reason = error?.details?.reason;
37
+ return typeof reason === 'string' && Object.hasOwn(VAT_REFUSAL_STATUS, reason) &&
38
+ VAT_REFUSAL_STATUS[reason] === error?.statusCode
39
+ ? reason
40
+ : null;
41
+ }
42
+ /**
43
+ * Whether a refusal says the token's vault session is over: an invalid or an
44
+ * expired token, which only a new unseal replaces, so a client forgets it. A
45
+ * read-only refusal leaves the session standing (the token still reads), and
46
+ * so does a refusal that names no VAT reason.
47
+ *
48
+ * @param {string|null} reason - What vatRefusalReason returned
49
+ * @returns {boolean}
50
+ */
51
+ export function endsVatSession(reason) {
52
+ return reason === VAT_REFUSAL_REASONS.INVALID || reason === VAT_REFUSAL_REASONS.EXPIRED;
53
+ }
54
+ /**
55
+ * True when Core refused the request's login, not a Vault Access Token it
56
+ * carried: a 401 bearing Core's session code (AUTHENTICATION_ERROR, the
57
+ * mapped error's `upstreamCode`) that names no VAT refusal. Its token was
58
+ * refused, or its account is unavailable (details.reason ACCOUNT_UNAVAILABLE,
59
+ * ./refusal-reasons.js). A 401 for a credential in the request body (an
60
+ * unseal key) carries Core's credential code (UNAUTHORIZED) and is not one.
61
+ *
62
+ * @param {{ statusCode?: number, upstreamCode?: string|null, details?: { reason?: string } }} error -
63
+ * An error as parsed from a Core response (parseApiError)
64
+ * @returns {boolean}
65
+ */
66
+ export function isRefusedLogin(error) {
67
+ return error?.statusCode === 401 && error?.upstreamCode === 'AUTHENTICATION_ERROR' && vatRefusalReason(error) === null;
68
+ }
69
+ //# sourceMappingURL=vat-refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vat-refusal.js","sourceRoot":"","sources":["../../src/app-sdk/vat-refusal.js"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,uDAAuD;AACvD,8DAA8D;AAE9D;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/C,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,aAAa;IACtB,SAAS,EAAE,eAAe;CAC3B,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9C,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,GAAG;IAClC,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,GAAG;IAClC,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,GAAG;CACrC,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAK;IACpC,MAAM,MAAM,GAAG,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;IACtC,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC;QAC5E,kBAAkB,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,UAAU;QAChD,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,MAAM;IACnC,OAAO,MAAM,KAAK,mBAAmB,CAAC,OAAO,IAAI,MAAM,KAAK,mBAAmB,CAAC,OAAO,CAAC;AAC1F,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,KAAK;IAClC,OAAO,KAAK,EAAE,UAAU,KAAK,GAAG,IAAI,KAAK,EAAE,YAAY,KAAK,sBAAsB,IAAI,gBAAgB,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AACzH,CAAC"}
package/dist/billing.d.ts CHANGED
@@ -1,27 +1,19 @@
1
1
  import type { MobileHttpClient } from './http.js';
2
- import type { IapPlatform, SparkVaultSubscription } from './types.js';
3
- /** Short-lived Stripe Customer Portal URL for managing the subscription on web. */
4
- export interface PortalSession {
5
- portal_url: string;
6
- }
2
+ import type { IapPlatform, IapValidation, SparkVaultSubscription } from './types.js';
7
3
  export declare class MobileBillingClient {
8
4
  private readonly http;
9
5
  constructor(http: MobileHttpClient);
10
6
  /**
11
- * Current subscription: plan, licensed vs. used seats, capacity blocks, live
12
- * pool usage, and Identity attempts. Drives the subscription / usage view.
7
+ * Current subscription: billing lifecycle, licensed vs. used seats, capacity
8
+ * blocks, live pool usage, and Identity attempts. Drives the subscription /
9
+ * usage view.
13
10
  */
14
11
  getSubscription(): Promise<SparkVaultSubscription>;
15
12
  /**
16
- * Open the Stripe Customer Portal to manage the subscription on web (seat /
17
- * block changes that fixed native SKUs cannot carry route here). The caller
18
- * loads the returned URL in the WebView.
19
- */
20
- createPortalSession(): Promise<PortalSession>;
21
- /**
22
- * Validate a native in-app purchase receipt server-side and apply the
23
- * resulting entitlements. Returns the refreshed subscription so the client
24
- * can update its plan / usage view immediately after purchase.
13
+ * Validate a native in-app purchase server-side and apply the entitlements
14
+ * it buys. `receipt` is the App Store signed transaction (JWS) or the Play
15
+ * purchase token. Answers whether Core provisioned the purchase; read the
16
+ * subscription again with getSubscription() to show the change.
25
17
  */
26
- iapValidate(platform: IapPlatform, productId: string, receipt: string): Promise<SparkVaultSubscription>;
18
+ iapValidate(platform: IapPlatform, productId: string, receipt: string): Promise<IapValidation>;
27
19
  }
package/dist/billing.js CHANGED
@@ -1,34 +1,31 @@
1
+ import { apiPath } from './request-path.js';
1
2
  export class MobileBillingClient {
2
3
  constructor(http) {
3
4
  this.http = http;
4
5
  }
5
6
  /**
6
- * Current subscription: plan, licensed vs. used seats, capacity blocks, live
7
- * pool usage, and Identity attempts. Drives the subscription / usage view.
7
+ * Current subscription: billing lifecycle, licensed vs. used seats, capacity
8
+ * blocks, live pool usage, and Identity attempts. Drives the subscription /
9
+ * usage view.
8
10
  */
9
11
  async getSubscription() {
10
- const response = await this.http.get('/billing/subscription');
12
+ const response = await this.http.get(apiPath `/billing/subscription`);
11
13
  return response.data;
12
14
  }
13
15
  /**
14
- * Open the Stripe Customer Portal to manage the subscription on web (seat /
15
- * block changes that fixed native SKUs cannot carry route here). The caller
16
- * loads the returned URL in the WebView.
17
- */
18
- async createPortalSession() {
19
- const response = await this.http.post('/billing/portal');
20
- return response.data;
21
- }
22
- /**
23
- * Validate a native in-app purchase receipt server-side and apply the
24
- * resulting entitlements. Returns the refreshed subscription so the client
25
- * can update its plan / usage view immediately after purchase.
16
+ * Validate a native in-app purchase server-side and apply the entitlements
17
+ * it buys. `receipt` is the App Store signed transaction (JWS) or the Play
18
+ * purchase token. Answers whether Core provisioned the purchase; read the
19
+ * subscription again with getSubscription() to show the change.
26
20
  */
27
21
  async iapValidate(platform, productId, receipt) {
28
- const response = await this.http.post('/billing/iap/validate', {
22
+ // Core reads an App Store purchase's signed transaction as `receipt` and a
23
+ // Play purchase's token as `purchase_token`.
24
+ const credential = platform === 'android' ? { purchase_token: receipt } : { receipt };
25
+ const response = await this.http.post(apiPath `/billing/iap/validate`, {
29
26
  platform,
30
27
  product_id: productId,
31
- receipt,
28
+ ...credential,
32
29
  });
33
30
  return response.data;
34
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"billing.js","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,mBAAmB;IAG9B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAyB,uBAAuB,CAAC,CAAC;QACtF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAgB,iBAAiB,CAAC,CAAC;QACxE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CACf,QAAqB,EACrB,SAAiB,EACjB,OAAe;QAEf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAyB,uBAAuB,EAAE;YACrF,QAAQ;YACR,UAAU,EAAE,SAAS;YACrB,OAAO;SACR,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"billing.js","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,MAAM,OAAO,mBAAmB;IAG9B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAyB,OAAO,CAAA,uBAAuB,CAAC,CAAC;QAC7F,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CACf,QAAqB,EACrB,SAAiB,EACjB,OAAe;QAEf,2EAA2E;QAC3E,6CAA6C;QAC7C,MAAM,UAAU,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QACtF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAgB,OAAO,CAAA,uBAAuB,EAAE;YACnF,QAAQ;YACR,UAAU,EAAE,SAAS;YACrB,GAAG,UAAU;SACd,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
package/dist/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { FetchLike, MobileBackgroundTransfer, MobileBackgroundUploader, MobileFileDownloader, MobileFileReader, SparkVaultLogger, TokenStorageAdapter } from './types.js';
2
+ import { type ApiPath } from './request-path.js';
2
3
  export interface SparkVaultMobileConfig {
3
4
  tokenStorage: TokenStorageAdapter;
4
5
  apiBaseUrl?: string;
@@ -8,6 +9,11 @@ export interface SparkVaultMobileConfig {
8
9
  userAgent?: string;
9
10
  timeoutMs?: number;
10
11
  fileTransferTimeoutMs?: number;
12
+ /**
13
+ * Timeout of a tus create POST and DELETE. A HEAD and the receipt (the
14
+ * PATCH at the final offset) wait HEAD_AND_RECEIPT_TIMEOUT_MS instead:
15
+ * Forge answers either only after its own call to Core.
16
+ */
11
17
  tusPostTimeoutMs?: number;
12
18
  /** Stall watchdog per tus chunk PATCH: aborts after this long with NO upload progress (not an absolute deadline). */
13
19
  tusChunkTimeoutMs?: number;
@@ -30,9 +36,34 @@ export interface SparkVaultMobileConfig {
30
36
  * upload, and every upload when this is unset, streams over XHR.
31
37
  */
32
38
  backgroundUploader?: MobileBackgroundUploader;
39
+ /**
40
+ * Whether the device has a network path right now (an app wires it to its
41
+ * OS network signal). Read when an upload request got no answer: while it
42
+ * answers false the upload waits for `onOnline` instead of spending its
43
+ * retries, then asks Forge where the session stands. Only a definite
44
+ * "offline" should answer false; a path that may come up is online. Given
45
+ * together with `onOnline`, or not at all.
46
+ */
47
+ isOnline?: () => boolean;
48
+ /**
49
+ * Subscribe to the network coming back; returns the unsubscribe. The pair
50
+ * of `isOnline`. A wait it ends is otherwise ended only by the upload's
51
+ * `abortSignal`.
52
+ */
53
+ onOnline?: (listener: () => void) => () => void;
33
54
  logger?: Partial<SparkVaultLogger>;
55
+ /**
56
+ * Host allowlist for the backend-issued Forge transfer URLs the SDK sends an
57
+ * ingot's ISTK to (downloads and uploads alike). Defaults to the SparkVault
58
+ * platform's own hosts; override only when pointing at another deployment.
59
+ */
34
60
  allowedDownloadHostPatterns?: RegExp[];
35
61
  }
62
+ /** The device's network signal, as the upload's offline wait reads it (`isOnline` with `onOnline`). */
63
+ export interface MobileConnectivity {
64
+ isOnline(): boolean;
65
+ onOnline(listener: () => void): () => void;
66
+ }
36
67
  export interface ResolvedMobileConfig {
37
68
  tokenStorage: TokenStorageAdapter;
38
69
  apiBaseUrl: string;
@@ -49,8 +80,9 @@ export interface ResolvedMobileConfig {
49
80
  fileDownloader?: MobileFileDownloader;
50
81
  backgroundTransfer?: MobileBackgroundTransfer;
51
82
  backgroundUploader?: MobileBackgroundUploader;
83
+ connectivity?: MobileConnectivity;
52
84
  logger: SparkVaultLogger;
53
85
  allowedDownloadHostPatterns: RegExp[];
54
86
  }
55
87
  export declare function resolveMobileConfig(config: SparkVaultMobileConfig): ResolvedMobileConfig;
56
- export declare function identityUrl(config: ResolvedMobileConfig, path: string): string;
88
+ export declare function identityUrl(config: ResolvedMobileConfig, path: ApiPath): string;
package/dist/config.js CHANGED
@@ -1,24 +1,27 @@
1
1
  import { SparkVaultValidationError } from './errors.js';
2
- import { SPARKVAULT_PLATFORM_SV_HOSTS, SPARKVAULT_ROOT_DOMAIN, } from './platform-domains.generated.js';
2
+ import { isResourceIdOf } from './app-sdk/ids.js';
3
+ import { SPARKVAULT_IDENTITY_HOST, SPARKVAULT_OWNED_HOST_PATTERNS } from './app-sdk/platform-domains.js';
4
+ import { apiPath } from './request-path.js';
3
5
  const DEFAULT_API_BASE_URL = 'https://api.sparkvault.com/v1';
4
- const DEFAULT_IDENTITY_BASE_URL = 'https://auth.sparkvault.com';
5
- function escapeRegExp(value) {
6
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
7
- }
8
- // Hosts that are allowed to serve backend-issued ingot download URLs, derived
9
- // from the canonical platform domain registry baked in at build time.
10
- const DEFAULT_ALLOWED_DOWNLOAD_HOST_PATTERNS = [
11
- new RegExp(`(^|\\.)${escapeRegExp(SPARKVAULT_ROOT_DOMAIN)}$`, 'i'),
12
- new RegExp(`(^|\\.)(${SPARKVAULT_PLATFORM_SV_HOSTS.map(escapeRegExp).join('|')})$`, 'i'),
13
- /\.amazonaws\.com$/i,
14
- /\.cloudfront\.net$/i,
15
- ];
6
+ const DEFAULT_IDENTITY_BASE_URL = `https://${SPARKVAULT_IDENTITY_HOST}`;
16
7
  const noopLogger = {
17
8
  debug: () => undefined,
18
9
  info: () => undefined,
19
10
  warn: () => undefined,
20
11
  error: () => undefined,
21
12
  };
13
+ /** The `isOnline` / `onOnline` pair as one signal, or none: one without the other cannot wait for the network. */
14
+ function resolveConnectivity(config) {
15
+ const { isOnline, onOnline } = config;
16
+ if (isOnline === undefined && onOnline === undefined)
17
+ return undefined;
18
+ if (typeof isOnline !== 'function' || typeof onOnline !== 'function') {
19
+ throw new SparkVaultValidationError('isOnline and onOnline are given together, as functions', {
20
+ field: typeof isOnline === 'function' ? 'onOnline' : 'isOnline',
21
+ });
22
+ }
23
+ return { isOnline, onOnline };
24
+ }
22
25
  function normalizeBaseUrl(url, field) {
23
26
  if (!url || typeof url !== 'string') {
24
27
  throw new SparkVaultValidationError(`${field} must be a non-empty string`, { field });
@@ -60,8 +63,10 @@ export function resolveMobileConfig(config) {
60
63
  received: identityAccountId,
61
64
  });
62
65
  }
63
- if (!identityAccountId.startsWith('acc_')) {
64
- throw new SparkVaultValidationError('identityAccountId must start with "acc_"', {
66
+ // The account id names Identity request paths: the platform's one id
67
+ // grammar keeps it a single path segment.
68
+ if (!isResourceIdOf('account', identityAccountId)) {
69
+ throw new SparkVaultValidationError('identityAccountId must be a SparkVault account id (acc_...)', {
65
70
  field: 'identityAccountId',
66
71
  received: identityAccountId,
67
72
  });
@@ -82,11 +87,12 @@ export function resolveMobileConfig(config) {
82
87
  fileDownloader: config.fileDownloader,
83
88
  backgroundTransfer: config.backgroundTransfer,
84
89
  backgroundUploader: config.backgroundUploader,
90
+ connectivity: resolveConnectivity(config),
85
91
  logger: { ...noopLogger, ...config.logger },
86
- allowedDownloadHostPatterns: config.allowedDownloadHostPatterns ?? DEFAULT_ALLOWED_DOWNLOAD_HOST_PATTERNS,
92
+ allowedDownloadHostPatterns: config.allowedDownloadHostPatterns ?? [...SPARKVAULT_OWNED_HOST_PATTERNS],
87
93
  };
88
94
  }
89
95
  export function identityUrl(config, path) {
90
- return `${config.identityBaseUrl}/${config.identityAccountId}${path}`;
96
+ return `${config.identityBaseUrl}${apiPath `/${config.identityAccountId}`}${path}`;
91
97
  }
92
98
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAUzG,OAAO,EAAE,OAAO,EAAgB,MAAM,mBAAmB,CAAC;AAE1D,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAC7D,MAAM,yBAAyB,GAAG,WAAW,wBAAwB,EAAE,CAAC;AAExE,MAAM,UAAU,GAAqB;IACnC,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;IACtB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;CACvB,CAAC;AAyFF,kHAAkH;AAClH,SAAS,mBAAmB,CAAC,MAA8B;IACzD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACvE,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACrE,MAAM,IAAI,yBAAyB,CAAC,wDAAwD,EAAE;YAC5F,KAAK,EAAE,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;SAChE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,KAAa;IAClD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,yBAAyB,CAAC,GAAG,KAAK,6BAA6B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,YAAY,CACnB,GAAW,EACX,OAA8C;IAE9C,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,yBAAyB,CAAC,oDAAoD,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAA8B;IAChE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACzB,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACnD,IAAI,CAAC,iBAAiB,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,yBAAyB,CAAC,+BAA+B,EAAE;YACnE,KAAK,EAAE,mBAAmB;YAC1B,QAAQ,EAAE,iBAAiB;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,0CAA0C;IAC1C,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,yBAAyB,CAAC,6DAA6D,EAAE;YACjG,KAAK,EAAE,mBAAmB;YAC1B,QAAQ,EAAE,iBAAiB;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,UAAU,IAAI,oBAAoB,EAAE,YAAY,CAAC;QACrF,eAAe,EAAE,gBAAgB,CAAC,MAAM,CAAC,eAAe,IAAI,yBAAyB,EAAE,iBAAiB,CAAC;QACzG,iBAAiB;QACjB,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,IAAI,IAAI;QAC3D,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,2BAA2B;QAC1D,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QACpC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,IAAI,MAAM;QAC7D,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,KAAK;QAClD,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,MAAM;QACrD,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,YAAY;QACnC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,YAAY,EAAE,mBAAmB,CAAC,MAAM,CAAC;QACzC,MAAM,EAAE,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;QAC3C,2BAA2B,EAAE,MAAM,CAAC,2BAA2B,IAAI,CAAC,GAAG,8BAA8B,CAAC;KACvG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAA4B,EAAE,IAAa;IACrE,OAAO,GAAG,MAAM,CAAC,eAAe,GAAG,OAAO,CAAA,IAAI,MAAM,CAAC,iBAAiB,EAAE,GAAG,IAAI,EAAE,CAAC;AACpF,CAAC"}
@@ -1,7 +1,33 @@
1
+ /**
2
+ * Base64 and UTF-8 for the mobile SDK.
3
+ *
4
+ * The base64 codec is the platform's one copy, mirrored from
5
+ * `@sparkvault/app-sdk/encoding` into `./app-sdk/encoding.js`; the decoders here
6
+ * raise this SDK's validation error where that codec refuses a text. UTF-8 is
7
+ * converted here rather than with TextEncoder/TextDecoder, which the JavaScript
8
+ * engines of the React Native versions this SDK supports need not provide.
9
+ * Decoding UTF-8 is fatal: bytes that are not UTF-8 are refused, never read as
10
+ * invented characters.
11
+ */
12
+ import { bytesToBase64, bytesToBase64url } from './app-sdk/encoding.js';
13
+ export { bytesToBase64, bytesToBase64url };
14
+ /**
15
+ * Decode standard base64.
16
+ * @throws SparkVaultValidationError when the text is not base64
17
+ */
18
+ export declare function base64ToBytes(value: string): Uint8Array;
19
+ /**
20
+ * Decode base64url.
21
+ * @throws SparkVaultValidationError when the text is not base64url
22
+ */
23
+ export declare function base64UrlToBytes(value: string): Uint8Array;
1
24
  export declare function utf8ToBytes(value: string): Uint8Array;
2
- export declare function base64EncodeUtf8(value: string): string;
25
+ /**
26
+ * Decode UTF-8 by the WHATWG decoder's rules in fatal mode: a byte that cannot
27
+ * start a sequence, a sequence cut short, an overlong form, a surrogate or a
28
+ * code point past U+10FFFF refuses the whole input.
29
+ * @throws SparkVaultValidationError when the bytes are not UTF-8
30
+ */
3
31
  export declare function bytesToUtf8(bytes: Uint8Array): string;
4
- export declare function base64UrlToBytes(value: string): Uint8Array;
32
+ export declare function base64EncodeUtf8(value: string): string;
5
33
  export declare function base64UrlToUtf8(value: string): string;
6
- export declare function bytesToBase64(bytes: Uint8Array): string;
7
- export declare function base64ToBytes(value: string): Uint8Array;