@evolu/common 6.0.1-preview.9 → 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 (184) hide show
  1. package/README.md +2 -2
  2. package/dist/src/Array.d.ts +256 -12
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +215 -9
  5. package/dist/src/Assert.d.ts +0 -13
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +0 -15
  8. package/dist/src/Brand.d.ts +75 -0
  9. package/dist/src/Brand.d.ts.map +1 -0
  10. package/dist/src/Brand.js +1 -0
  11. package/dist/src/Buffer.d.ts +1 -1
  12. package/dist/src/Buffer.d.ts.map +1 -1
  13. package/dist/src/Buffer.js +8 -7
  14. package/dist/src/Cache.d.ts +44 -0
  15. package/dist/src/Cache.d.ts.map +1 -0
  16. package/dist/src/Cache.js +52 -0
  17. package/dist/src/Callbacks.d.ts +45 -12
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Callbacks.js +14 -7
  20. package/dist/src/Console.d.ts +31 -6
  21. package/dist/src/Console.d.ts.map +1 -1
  22. package/dist/src/Console.js +72 -9
  23. package/dist/src/Crypto.d.ts +56 -42
  24. package/dist/src/Crypto.d.ts.map +1 -1
  25. package/dist/src/Crypto.js +40 -53
  26. package/dist/src/Evolu/Db.d.ts +162 -74
  27. package/dist/src/Evolu/Db.d.ts.map +1 -1
  28. package/dist/src/Evolu/Db.js +284 -702
  29. package/dist/src/Evolu/Diff.d.ts +3 -3
  30. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  31. package/dist/src/Evolu/Diff.js +7 -5
  32. package/dist/src/Evolu/Evolu.d.ts +213 -133
  33. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  34. package/dist/src/Evolu/Evolu.js +189 -180
  35. package/dist/src/Evolu/Internal.d.ts +0 -2
  36. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  37. package/dist/src/Evolu/Internal.js +0 -2
  38. package/dist/src/Evolu/LocalAuth.d.ts +150 -0
  39. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  40. package/dist/src/Evolu/LocalAuth.js +174 -0
  41. package/dist/src/Evolu/Owner.d.ts +273 -120
  42. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  43. package/dist/src/Evolu/Owner.js +130 -104
  44. package/dist/src/Evolu/Platform.d.ts +9 -7
  45. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  46. package/dist/src/Evolu/Protocol.d.ts +268 -240
  47. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  48. package/dist/src/Evolu/Protocol.js +595 -447
  49. package/dist/src/Evolu/Public.d.ts +6 -8
  50. package/dist/src/Evolu/Public.d.ts.map +1 -1
  51. package/dist/src/Evolu/Public.js +2 -3
  52. package/dist/src/Evolu/PublicKysely.d.ts.map +1 -1
  53. package/dist/src/Evolu/PublicKysely.js +3 -4
  54. package/dist/src/Evolu/Query.d.ts +2 -1
  55. package/dist/src/Evolu/Query.d.ts.map +1 -1
  56. package/dist/src/Evolu/Query.js +1 -1
  57. package/dist/src/Evolu/Relay.d.ts +91 -8
  58. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  59. package/dist/src/Evolu/Relay.js +214 -88
  60. package/dist/src/Evolu/Schema.d.ts +125 -47
  61. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  62. package/dist/src/Evolu/Schema.js +175 -31
  63. package/dist/src/Evolu/Storage.d.ts +249 -27
  64. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  65. package/dist/src/Evolu/Storage.js +198 -92
  66. package/dist/src/Evolu/Sync.d.ts +68 -13
  67. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  68. package/dist/src/Evolu/Sync.js +469 -20
  69. package/dist/src/Evolu/Timestamp.d.ts +83 -30
  70. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  71. package/dist/src/Evolu/Timestamp.js +79 -34
  72. package/dist/src/Identicon.d.ts +35 -0
  73. package/dist/src/Identicon.d.ts.map +1 -0
  74. package/dist/src/Identicon.js +143 -0
  75. package/dist/src/Instances.d.ts +34 -0
  76. package/dist/src/Instances.d.ts.map +1 -0
  77. package/dist/src/Instances.js +44 -0
  78. package/dist/src/Number.d.ts +4 -3
  79. package/dist/src/Number.d.ts.map +1 -1
  80. package/dist/src/Number.js +5 -4
  81. package/dist/src/Object.d.ts +10 -4
  82. package/dist/src/Object.d.ts.map +1 -1
  83. package/dist/src/Object.js +9 -3
  84. package/dist/src/Platform.d.ts +20 -0
  85. package/dist/src/Platform.d.ts.map +1 -0
  86. package/dist/src/Platform.js +22 -0
  87. package/dist/src/Random.d.ts +3 -2
  88. package/dist/src/Random.d.ts.map +1 -1
  89. package/dist/src/Relation.d.ts +79 -0
  90. package/dist/src/Relation.d.ts.map +1 -0
  91. package/dist/src/Relation.js +127 -0
  92. package/dist/src/Resources.d.ts +118 -0
  93. package/dist/src/Resources.d.ts.map +1 -0
  94. package/dist/src/Resources.js +197 -0
  95. package/dist/src/Result.d.ts +184 -52
  96. package/dist/src/Result.d.ts.map +1 -1
  97. package/dist/src/Result.js +30 -241
  98. package/dist/src/Skiplist.js +2 -1
  99. package/dist/src/Sqlite.d.ts +89 -5
  100. package/dist/src/Sqlite.d.ts.map +1 -1
  101. package/dist/src/Sqlite.js +136 -9
  102. package/dist/src/Task.d.ts +586 -0
  103. package/dist/src/Task.d.ts.map +1 -0
  104. package/dist/src/Task.js +469 -0
  105. package/dist/src/Time.d.ts +66 -1
  106. package/dist/src/Time.d.ts.map +1 -1
  107. package/dist/src/Time.js +99 -5
  108. package/dist/src/Type.d.ts +676 -343
  109. package/dist/src/Type.d.ts.map +1 -1
  110. package/dist/src/Type.js +718 -467
  111. package/dist/src/Types.d.ts +1 -75
  112. package/dist/src/Types.d.ts.map +1 -1
  113. package/dist/src/WebSocket.d.ts +5 -2
  114. package/dist/src/WebSocket.d.ts.map +1 -1
  115. package/dist/src/WebSocket.js +12 -18
  116. package/dist/src/Worker.d.ts +39 -11
  117. package/dist/src/Worker.d.ts.map +1 -1
  118. package/dist/src/Worker.js +22 -4
  119. package/dist/src/index.d.ts +8 -3
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +8 -3
  122. package/package.json +14 -13
  123. package/src/Array.ts +301 -19
  124. package/src/Assert.ts +0 -21
  125. package/src/Brand.ts +75 -0
  126. package/src/Buffer.ts +7 -7
  127. package/src/Cache.ts +85 -0
  128. package/src/Callbacks.ts +62 -22
  129. package/src/Console.ts +91 -11
  130. package/src/Crypto.ts +94 -90
  131. package/src/Evolu/Db.ts +519 -1026
  132. package/src/Evolu/Diff.ts +7 -5
  133. package/src/Evolu/Evolu.ts +476 -360
  134. package/src/Evolu/Internal.ts +0 -2
  135. package/src/Evolu/LocalAuth.ts +463 -0
  136. package/src/Evolu/Owner.ts +355 -228
  137. package/src/Evolu/Platform.ts +9 -9
  138. package/src/Evolu/Protocol.ts +846 -742
  139. package/src/Evolu/Public.ts +7 -14
  140. package/src/Evolu/PublicKysely.ts +4 -5
  141. package/src/Evolu/Query.ts +3 -2
  142. package/src/Evolu/Relay.ts +406 -103
  143. package/src/Evolu/Schema.ts +323 -91
  144. package/src/Evolu/Storage.ts +559 -137
  145. package/src/Evolu/Sync.ts +819 -36
  146. package/src/Evolu/Timestamp.ts +90 -58
  147. package/src/Identicon.ts +197 -0
  148. package/src/Instances.ts +90 -0
  149. package/src/Number.ts +6 -10
  150. package/src/Object.ts +13 -5
  151. package/src/Platform.ts +26 -0
  152. package/src/Random.ts +3 -2
  153. package/src/Relation.ts +234 -0
  154. package/src/Resources.ts +367 -0
  155. package/src/Result.ts +191 -54
  156. package/src/Skiplist.ts +1 -1
  157. package/src/Sqlite.ts +152 -17
  158. package/src/Task.ts +901 -0
  159. package/src/Time.ts +180 -5
  160. package/src/Type.ts +1135 -730
  161. package/src/Types.ts +1 -77
  162. package/src/WebSocket.ts +27 -25
  163. package/src/Worker.ts +72 -23
  164. package/src/index.ts +8 -3
  165. package/dist/src/Evolu/Config.d.ts +0 -69
  166. package/dist/src/Evolu/Config.d.ts.map +0 -1
  167. package/dist/src/Evolu/Config.js +0 -9
  168. package/dist/src/Evolu/Kysely.d.ts +0 -6
  169. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  170. package/dist/src/Evolu/Kysely.js +0 -21
  171. package/dist/src/ManyToManyMap.d.ts +0 -26
  172. package/dist/src/ManyToManyMap.d.ts.map +0 -1
  173. package/dist/src/ManyToManyMap.js +0 -92
  174. package/dist/src/NanoId.d.ts +0 -27
  175. package/dist/src/NanoId.d.ts.map +0 -1
  176. package/dist/src/NanoId.js +0 -6
  177. package/dist/src/Promise.d.ts +0 -180
  178. package/dist/src/Promise.d.ts.map +0 -1
  179. package/dist/src/Promise.js +0 -176
  180. package/src/Evolu/Config.ts +0 -83
  181. package/src/Evolu/Kysely.ts +0 -38
  182. package/src/ManyToManyMap.ts +0 -140
  183. package/src/NanoId.ts +0 -39
  184. package/src/Promise.ts +0 -295
@@ -0,0 +1,150 @@
1
+ import { RandomBytesDep } from "../Crypto.js";
2
+ import { Mnemonic } from "../Type.js";
3
+ import { AppOwner, OwnerId } from "./Owner.js";
4
+ /**
5
+ * Local authentication and authorization system for Evolu. This is API is
6
+ * subject to change and not recommended for production use.
7
+ *
8
+ * @experimental
9
+ */
10
+ export interface LocalAuth {
11
+ /** Logs in with the given owner ID, or loads the target owner if not provided. */
12
+ login: (ownerId: OwnerId, options?: LocalAuthOptions) => Promise<AuthResult | null>;
13
+ /** Registers a new owner with the given username. */
14
+ register: (username: string, options?: LocalAuthOptions & {
15
+ mnemonic?: Mnemonic | null;
16
+ }) => Promise<AuthResult | null>;
17
+ /** Unregisters an owner with the given owner ID. */
18
+ unregister: (ownerId: OwnerId, options?: LocalAuthOptions) => Promise<void>;
19
+ /** Gets the current owner (last logged in or last registered owner) */
20
+ getOwner: (options?: LocalAuthOptions) => Promise<AuthResult | null>;
21
+ /** Lists all registered owner ids with associated usernames. */
22
+ getProfiles: (options?: LocalAuthOptionsValues) => Promise<Array<AuthList>>;
23
+ /** Clears all owners and metadata from the local auth. */
24
+ clearAll: (options?: LocalAuthOptions) => Promise<void>;
25
+ }
26
+ export interface LocalAuthDep {
27
+ readonly localAuth: LocalAuth;
28
+ }
29
+ /**
30
+ * - **⚠️
31
+ *
32
+ * Secure storage interface that must be implemented by each platform.
33
+ */
34
+ export interface SecureStorage {
35
+ setItem: (key: string, value: string, options?: LocalAuthOptions) => Promise<MutationResult>;
36
+ getItem: (key: string, options?: LocalAuthOptionsValues) => Promise<SensitiveInfoItem | null>;
37
+ deleteItem: (key: string, options?: LocalAuthOptions) => Promise<boolean>;
38
+ getAllItems: (options?: LocalAuthOptionsValues) => Promise<Array<SensitiveInfoItem>>;
39
+ clearService: (options?: LocalAuthOptions) => Promise<void>;
40
+ }
41
+ export interface SecureStorageDep {
42
+ readonly secureStorage: SecureStorage;
43
+ }
44
+ /**
45
+ * Creates a local auth using the given secure storage implementation. This
46
+ * factory function allows each platform to provide its own storage layer while
47
+ * sharing the common auth logic.
48
+ */
49
+ export declare const createLocalAuth: (deps: SecureStorageDep & RandomBytesDep) => LocalAuth;
50
+ export declare const localAuth_Namespace = "evolu";
51
+ export declare const localAuthDefaultOptions: LocalAuthOptions;
52
+ export interface AuthResult {
53
+ /** The app owner created during registration. */
54
+ readonly owner: AppOwner | undefined;
55
+ /** The name provided by the user during registration. */
56
+ readonly username: string;
57
+ }
58
+ export interface AuthList {
59
+ /** The app owner ID. */
60
+ readonly ownerId: OwnerId;
61
+ /** The name provided by the user during registration. */
62
+ readonly username: string;
63
+ }
64
+ export interface LocalAuthOptions {
65
+ /**
66
+ * Native: Namespaces the stored entry. Defaults to the bundle identifier
67
+ * (when available) or `default`.
68
+ */
69
+ readonly service?: string;
70
+ /** IOS: Enable keychain item synchronization via iCloud. */
71
+ readonly iosSynchronizable?: boolean;
72
+ /** IOS: Custom keychain access group. */
73
+ readonly keychainGroup?: string;
74
+ /**
75
+ * Native: Desired access-control policy. The native implementation will
76
+ * automatically fall back to the strongest supported policy for the current
77
+ * device (Secure Enclave ➝ Biometry ➝ Device Credential ➝ None).
78
+ */
79
+ readonly accessControl?: AccessControl;
80
+ /**
81
+ * Android: Fine tune whether the hardware-authenticated key should require
82
+ * biometrics only.
83
+ */
84
+ readonly androidBiometricsStrongOnly?: boolean;
85
+ /**
86
+ * Native: Optional prompt configuration that will be shown when protected
87
+ * keys require user presence.
88
+ */
89
+ readonly authenticationPrompt?: AuthenticationPrompt;
90
+ /** Web: The relying party ID for WebAuthn. Defaults to the current hostname. */
91
+ readonly relyingPartyID?: string;
92
+ /** Web: The relying party name for WebAuthn. Defaults to 'Evolu'. */
93
+ readonly relyingPartyName?: string;
94
+ /** Web: The username for WebAuthn. Defaults to 'Evolu User'. */
95
+ readonly webAuthnUsername?: string;
96
+ /**
97
+ * Web: The user verification requirement for WebAuthn. Defaults to
98
+ * 'required'.
99
+ */
100
+ readonly webAuthnUserVerification?: UserVerificationRequirement;
101
+ /** Web: The authenticator attachment for WebAuthn. Defaults to 'platform'. */
102
+ readonly webAuthnAuthenticatorAttachment?: AuthenticatorAttachment;
103
+ }
104
+ export interface LocalAuthOptionsValues extends LocalAuthOptions {
105
+ /** When true, the stored value is returned for each item. Defaults to false. */
106
+ readonly includeValues?: boolean;
107
+ }
108
+ /**
109
+ * Configuration for the biometric/device credential prompt shown when a
110
+ * protected item is accessed.
111
+ */
112
+ export interface AuthenticationPrompt {
113
+ readonly title: string;
114
+ readonly subtitle?: string;
115
+ readonly description?: string;
116
+ readonly cancel?: string;
117
+ }
118
+ export interface SensitiveInfoGetRequest extends LocalAuthOptions {
119
+ readonly key: string;
120
+ /** Include the encrypted value when available. Defaults to true. */
121
+ readonly includeValue?: boolean;
122
+ }
123
+ export interface StorageMetadata {
124
+ readonly securityLevel: SecurityLevel;
125
+ readonly backend: StorageBackend;
126
+ readonly accessControl: AccessControl;
127
+ readonly timestamp: number;
128
+ }
129
+ export interface SensitiveInfoItem {
130
+ readonly key: string;
131
+ readonly service: string;
132
+ readonly value?: string;
133
+ readonly metadata: StorageMetadata;
134
+ }
135
+ export interface MutationResult {
136
+ readonly metadata: StorageMetadata;
137
+ }
138
+ /**
139
+ * Enumerates the highest security tier that was effectively applied while
140
+ * storing a value.
141
+ */
142
+ export type SecurityLevel = "secureEnclave" | "strongBox" | "biometry" | "deviceCredential" | "software";
143
+ /** Enumerates the native storage backend used to persist sensitive data. */
144
+ export type StorageBackend = "keychain" | "androidKeystore" | "encryptedSharedPreferences";
145
+ /**
146
+ * Enumerates the access-control policy enforced by the underlying secure
147
+ * storage.
148
+ */
149
+ export type AccessControl = "secureEnclaveBiometry" | "biometryCurrentSet" | "biometryAny" | "devicePasscode" | "none";
150
+ //# sourceMappingURL=LocalAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalAuth.d.ts","sourceRoot":"","sources":["../../../src/Evolu/LocalAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,QAAQ,EAKR,OAAO,EAER,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,KAAK,EAAE,CACL,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAEhC,qDAAqD;IACrD,QAAQ,EAAE,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE,KACxD,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAEhC,oDAAoD;IACpD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5E,uEAAuE;IACvE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAErE,gEAAgE;IAChE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5E,0DAA0D;IAC1D,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,OAAO,EAAE,CACP,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,sBAAsB,KAC7B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACvC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,WAAW,EAAE,CACX,OAAO,CAAC,EAAE,sBAAsB,KAC7B,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACvC,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,gBAAgB,GAAG,cAAc,KACtC,SAsOF,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,eAAO,MAAM,uBAAuB,EAAE,gBASrC,CAAC;AAKF,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IACrC,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,wBAAwB;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAID,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAErC,yCAAyC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAE/C;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAErD,gFAAgF;IAChF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC,qEAAqE;IACrE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAEnC,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAEnC;;;OAGG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,2BAA2B,CAAC;IAEhE,8EAA8E;IAC9E,QAAQ,CAAC,+BAA+B,CAAC,EAAE,uBAAuB,CAAC;CACpE;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,gFAAgF;IAChF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,eAAe,GACf,WAAW,GACX,UAAU,GACV,kBAAkB,GAClB,UAAU,CAAC;AAEf,4EAA4E;AAC5E,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,iBAAiB,GACjB,4BAA4B,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,uBAAuB,GACvB,oBAAoB,GACpB,aAAa,GACb,gBAAgB,GAChB,MAAM,CAAC"}
@@ -0,0 +1,174 @@
1
+ import { createAppOwner, createOwnerSecret, mnemonicToOwnerSecret, OwnerEncryptionKey, OwnerWriteKey, } from "./Owner.js";
2
+ /**
3
+ * Creates a local auth using the given secure storage implementation. This
4
+ * factory function allows each platform to provide its own storage layer while
5
+ * sharing the common auth logic.
6
+ */
7
+ export const createLocalAuth = (deps) => {
8
+ const setLastOwnerId = async (id, options) => {
9
+ await deps.secureStorage.setItem(localAuthMetakeyLastOwner, id, {
10
+ ...buildAuthOptions(options),
11
+ accessControl: "none",
12
+ });
13
+ };
14
+ const getLastOwnerId = async (options) => {
15
+ const item = await deps.secureStorage.getItem(localAuthMetakeyLastOwner, {
16
+ ...buildAuthOptions(options),
17
+ accessControl: "none",
18
+ });
19
+ return item?.value;
20
+ };
21
+ const getOwnerNames = async (options) => {
22
+ const item = await deps.secureStorage.getItem(localAuthMetakeyOwnerNames, {
23
+ ...buildAuthOptions(options),
24
+ accessControl: "none",
25
+ });
26
+ let names = {};
27
+ if (item?.value) {
28
+ names = JSON.parse(item.value);
29
+ }
30
+ return names;
31
+ };
32
+ const setOwnerName = async (id, username, options) => {
33
+ const names = await getOwnerNames(options);
34
+ names[id] = username;
35
+ await deps.secureStorage.setItem(localAuthMetakeyOwnerNames, JSON.stringify(names), {
36
+ ...buildAuthOptions(options),
37
+ accessControl: "none",
38
+ });
39
+ };
40
+ const deleteOwnerName = async (id, options) => {
41
+ const { [id]: _, ...names } = await getOwnerNames(options);
42
+ await deps.secureStorage.setItem(localAuthMetakeyOwnerNames, JSON.stringify(names), {
43
+ ...buildAuthOptions(options),
44
+ accessControl: "none",
45
+ });
46
+ };
47
+ const getOwnerIds = async (options) => {
48
+ const items = await deps.secureStorage.getAllItems({
49
+ ...buildAuthOptions(options),
50
+ includeValues: false,
51
+ });
52
+ return items
53
+ .filter(Boolean)
54
+ .filter((i) => i.key !== localAuthMetakeyLastOwner &&
55
+ i.key !== localAuthMetakeyOwnerNames)
56
+ .map((i) => i.key);
57
+ };
58
+ const clearAuthStore = (options) => deps.secureStorage.clearService(buildAuthOptions(options));
59
+ const buildAuthOptions = (options, username) => {
60
+ const newOptions = {
61
+ ...localAuthDefaultOptions,
62
+ ...(username && { webAuthnUsername: username }),
63
+ ...options,
64
+ };
65
+ return {
66
+ ...newOptions,
67
+ authenticationPrompt: {
68
+ title: replaceMessageTokens(newOptions.authenticationPrompt?.title ?? "", username),
69
+ cancel: replaceMessageTokens(newOptions.authenticationPrompt?.cancel ?? "", username),
70
+ subtitle: replaceMessageTokens(newOptions.authenticationPrompt?.subtitle ?? "", username),
71
+ description: replaceMessageTokens(newOptions.authenticationPrompt?.description ?? "", username),
72
+ },
73
+ };
74
+ };
75
+ const replaceMessageTokens = (text, username) => {
76
+ if (!username)
77
+ return text;
78
+ return text.replace("|USERNAME|", username);
79
+ };
80
+ return {
81
+ login: async (ownerId, options) => {
82
+ // Lookup the associated username
83
+ const names = await getOwnerNames(options);
84
+ const username = names[ownerId] ?? "";
85
+ // Currently a reload is needed. This avoids authentication
86
+ // it needs to be handled on next page load.
87
+ // We set the last owner so we know what the target is.
88
+ // It is the applications's responsibility to reload and trigger login.
89
+ await setLastOwnerId(ownerId, options);
90
+ return { owner: undefined, username };
91
+ },
92
+ register: async (username, options) => {
93
+ // Create an owner with a new secret or use specified mnemonic
94
+ const owner = createAppOwner(options?.mnemonic
95
+ ? mnemonicToOwnerSecret(options.mnemonic)
96
+ : createOwnerSecret(deps));
97
+ // Store owner, associated username, and update last owner
98
+ await Promise.all([
99
+ // setOwnerItem
100
+ deps.secureStorage.setItem(owner.id, JSON.stringify({ owner }), buildAuthOptions(options, username)),
101
+ setOwnerName(owner.id, username, options),
102
+ setLastOwnerId(owner.id, options),
103
+ ]);
104
+ // Return the owner and associated username
105
+ return { owner, username };
106
+ },
107
+ unregister: async (ownerId, options) => {
108
+ // Delete the owner and associated username
109
+ await Promise.all([
110
+ // deleteOwnerItem
111
+ deps.secureStorage.deleteItem(ownerId, buildAuthOptions(options)),
112
+ deleteOwnerName(ownerId, options),
113
+ ]);
114
+ // If the owner was the last owner then set to
115
+ // the next owner based on metadata timestamp
116
+ const lastOwnerId = await getLastOwnerId(options);
117
+ if (lastOwnerId === ownerId) {
118
+ const ids = await getOwnerIds(options);
119
+ if (ids.length > 0) {
120
+ await setLastOwnerId(ids[0], options);
121
+ }
122
+ }
123
+ },
124
+ getOwner: async (options) => {
125
+ const ownerId = await getLastOwnerId(options);
126
+ if (!ownerId)
127
+ return null;
128
+ const names = await getOwnerNames(options);
129
+ const username = names[ownerId] ?? "";
130
+ // Retrieve and decrypt the owner (this will trigger device authentication)
131
+ const account = await deps.secureStorage.getItem(ownerId, buildAuthOptions(options, username));
132
+ if (!account?.value)
133
+ return null;
134
+ // Unserialize the values (TODO: save these as base64 instead of json serializing)
135
+ const result = JSON.parse(account.value);
136
+ const writeKey = OwnerWriteKey.orThrow(new Uint8Array(Object.values(result.owner.writeKey)));
137
+ const encryptionKey = OwnerEncryptionKey.orThrow(new Uint8Array(Object.values(result.owner.encryptionKey)));
138
+ const owner = { ...result.owner, writeKey, encryptionKey };
139
+ // Update the last owner for future login attempts
140
+ await setLastOwnerId(ownerId, options);
141
+ // Return the owner and associated username
142
+ return { owner, username };
143
+ },
144
+ getProfiles: async (options) => {
145
+ // Get all owner ids and associated usernames
146
+ const [ids, names] = await Promise.all([
147
+ getOwnerIds(options),
148
+ getOwnerNames(options),
149
+ ]);
150
+ // Return the list of profiles (usually used for login UX)
151
+ return ids.map((ownerId) => ({
152
+ ownerId,
153
+ username: names[ownerId] ?? "",
154
+ }));
155
+ },
156
+ clearAll: async (options) => {
157
+ // Delete all owners and associated metadata (scoped to the service)
158
+ await clearAuthStore(options);
159
+ },
160
+ };
161
+ };
162
+ export const localAuth_Namespace = "evolu";
163
+ export const localAuthDefaultOptions = {
164
+ service: localAuth_Namespace,
165
+ keychainGroup: localAuth_Namespace,
166
+ androidBiometricsStrongOnly: true,
167
+ iosSynchronizable: true,
168
+ webAuthnUsername: "Evolu User",
169
+ authenticationPrompt: {
170
+ title: "Authenticate as |USERNAME|",
171
+ },
172
+ };
173
+ const localAuthMetakeyLastOwner = "_last_owner";
174
+ const localAuthMetakeyOwnerNames = "_owner_names";