@gettersethya/mira-client 0.1.0-alpha.2

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/client/auth.d.ts +66 -0
  3. package/dist/src/client/auth.d.ts.map +1 -0
  4. package/dist/src/client/auth.js +60 -0
  5. package/dist/src/client/auth.js.map +1 -0
  6. package/dist/src/client/collection.d.ts +239 -0
  7. package/dist/src/client/collection.d.ts.map +1 -0
  8. package/dist/src/client/collection.js +137 -0
  9. package/dist/src/client/collection.js.map +1 -0
  10. package/dist/src/client/errors.d.ts +46 -0
  11. package/dist/src/client/errors.d.ts.map +1 -0
  12. package/dist/src/client/errors.js +40 -0
  13. package/dist/src/client/errors.js.map +1 -0
  14. package/dist/src/client/factory.d.ts +76 -0
  15. package/dist/src/client/factory.d.ts.map +1 -0
  16. package/dist/src/client/factory.js +106 -0
  17. package/dist/src/client/factory.js.map +1 -0
  18. package/dist/src/client/file.d.ts +116 -0
  19. package/dist/src/client/file.d.ts.map +1 -0
  20. package/dist/src/client/file.js +99 -0
  21. package/dist/src/client/file.js.map +1 -0
  22. package/dist/src/client/handler.d.ts +92 -0
  23. package/dist/src/client/handler.d.ts.map +1 -0
  24. package/dist/src/client/handler.js +62 -0
  25. package/dist/src/client/handler.js.map +1 -0
  26. package/dist/src/client/index.d.ts +11 -0
  27. package/dist/src/client/index.d.ts.map +1 -0
  28. package/dist/src/client/index.js +6 -0
  29. package/dist/src/client/index.js.map +1 -0
  30. package/dist/src/client/types.d.ts +138 -0
  31. package/dist/src/client/types.d.ts.map +1 -0
  32. package/dist/src/client/types.js +2 -0
  33. package/dist/src/client/types.js.map +1 -0
  34. package/dist/src/collection/auth.d.ts +79 -0
  35. package/dist/src/collection/auth.d.ts.map +1 -0
  36. package/dist/src/collection/auth.js +50 -0
  37. package/dist/src/collection/auth.js.map +1 -0
  38. package/dist/src/collection/base.d.ts +64 -0
  39. package/dist/src/collection/base.d.ts.map +1 -0
  40. package/dist/src/collection/base.js +40 -0
  41. package/dist/src/collection/base.js.map +1 -0
  42. package/dist/src/collection/bytes.d.ts +51 -0
  43. package/dist/src/collection/bytes.d.ts.map +1 -0
  44. package/dist/src/collection/bytes.js +51 -0
  45. package/dist/src/collection/bytes.js.map +1 -0
  46. package/dist/src/collection/errors.d.ts +29 -0
  47. package/dist/src/collection/errors.d.ts.map +1 -0
  48. package/dist/src/collection/errors.js +23 -0
  49. package/dist/src/collection/errors.js.map +1 -0
  50. package/dist/src/collection/field.d.ts +300 -0
  51. package/dist/src/collection/field.d.ts.map +1 -0
  52. package/dist/src/collection/field.js +175 -0
  53. package/dist/src/collection/field.js.map +1 -0
  54. package/dist/src/collection/index-builder.d.ts +59 -0
  55. package/dist/src/collection/index-builder.d.ts.map +1 -0
  56. package/dist/src/collection/index-builder.js +43 -0
  57. package/dist/src/collection/index-builder.js.map +1 -0
  58. package/dist/src/collection/index.d.ts +22 -0
  59. package/dist/src/collection/index.d.ts.map +1 -0
  60. package/dist/src/collection/index.js +21 -0
  61. package/dist/src/collection/index.js.map +1 -0
  62. package/dist/src/collection/serialize.d.ts +24 -0
  63. package/dist/src/collection/serialize.d.ts.map +1 -0
  64. package/dist/src/collection/serialize.js +127 -0
  65. package/dist/src/collection/serialize.js.map +1 -0
  66. package/dist/src/collection/types.d.ts +119 -0
  67. package/dist/src/collection/types.d.ts.map +1 -0
  68. package/dist/src/collection/types.js +2 -0
  69. package/dist/src/collection/types.js.map +1 -0
  70. package/dist/src/collection/view.d.ts +57 -0
  71. package/dist/src/collection/view.d.ts.map +1 -0
  72. package/dist/src/collection/view.js +49 -0
  73. package/dist/src/collection/view.js.map +1 -0
  74. package/dist/src/filter/builder.d.ts +127 -0
  75. package/dist/src/filter/builder.d.ts.map +1 -0
  76. package/dist/src/filter/builder.js +72 -0
  77. package/dist/src/filter/builder.js.map +1 -0
  78. package/dist/src/filter/compiler.d.ts +48 -0
  79. package/dist/src/filter/compiler.d.ts.map +1 -0
  80. package/dist/src/filter/compiler.js +132 -0
  81. package/dist/src/filter/compiler.js.map +1 -0
  82. package/dist/src/filter/index.d.ts +6 -0
  83. package/dist/src/filter/index.d.ts.map +1 -0
  84. package/dist/src/filter/index.js +4 -0
  85. package/dist/src/filter/index.js.map +1 -0
  86. package/dist/src/filter/types.d.ts +96 -0
  87. package/dist/src/filter/types.d.ts.map +1 -0
  88. package/dist/src/filter/types.js +44 -0
  89. package/dist/src/filter/types.js.map +1 -0
  90. package/dist/src/index.d.ts +3 -0
  91. package/dist/src/index.d.ts.map +1 -0
  92. package/dist/src/index.js +3 -0
  93. package/dist/src/index.js.map +1 -0
  94. package/dist/src/rule/builder.d.ts +97 -0
  95. package/dist/src/rule/builder.d.ts.map +1 -0
  96. package/dist/src/rule/builder.js +126 -0
  97. package/dist/src/rule/builder.js.map +1 -0
  98. package/dist/src/rule/index.d.ts +3 -0
  99. package/dist/src/rule/index.d.ts.map +1 -0
  100. package/dist/src/rule/index.js +3 -0
  101. package/dist/src/rule/index.js.map +1 -0
  102. package/dist/src/rule/types.d.ts +129 -0
  103. package/dist/src/rule/types.d.ts.map +1 -0
  104. package/dist/src/rule/types.js +2 -0
  105. package/dist/src/rule/types.js.map +1 -0
  106. package/dist/tests/client/auth.test.d.ts +2 -0
  107. package/dist/tests/client/auth.test.d.ts.map +1 -0
  108. package/dist/tests/client/auth.test.js +67 -0
  109. package/dist/tests/client/auth.test.js.map +1 -0
  110. package/dist/tests/client/collection.test.d.ts +2 -0
  111. package/dist/tests/client/collection.test.d.ts.map +1 -0
  112. package/dist/tests/client/collection.test.js +543 -0
  113. package/dist/tests/client/collection.test.js.map +1 -0
  114. package/dist/tests/client/file.test.d.ts +2 -0
  115. package/dist/tests/client/file.test.d.ts.map +1 -0
  116. package/dist/tests/client/file.test.js +21 -0
  117. package/dist/tests/client/file.test.js.map +1 -0
  118. package/dist/tests/client/handler.test.d.ts +2 -0
  119. package/dist/tests/client/handler.test.d.ts.map +1 -0
  120. package/dist/tests/client/handler.test.js +24 -0
  121. package/dist/tests/client/handler.test.js.map +1 -0
  122. package/dist/tests/client/types.test.d.ts +2 -0
  123. package/dist/tests/client/types.test.d.ts.map +1 -0
  124. package/dist/tests/client/types.test.js +168 -0
  125. package/dist/tests/client/types.test.js.map +1 -0
  126. package/dist/tests/collection/auth.test.d.ts +2 -0
  127. package/dist/tests/collection/auth.test.d.ts.map +1 -0
  128. package/dist/tests/collection/auth.test.js +44 -0
  129. package/dist/tests/collection/auth.test.js.map +1 -0
  130. package/dist/tests/collection/base.test.d.ts +2 -0
  131. package/dist/tests/collection/base.test.d.ts.map +1 -0
  132. package/dist/tests/collection/base.test.js +70 -0
  133. package/dist/tests/collection/base.test.js.map +1 -0
  134. package/dist/tests/collection/bytes.test.d.ts +2 -0
  135. package/dist/tests/collection/bytes.test.d.ts.map +1 -0
  136. package/dist/tests/collection/bytes.test.js +9 -0
  137. package/dist/tests/collection/bytes.test.js.map +1 -0
  138. package/dist/tests/collection/field.test.d.ts +2 -0
  139. package/dist/tests/collection/field.test.d.ts.map +1 -0
  140. package/dist/tests/collection/field.test.js +140 -0
  141. package/dist/tests/collection/field.test.js.map +1 -0
  142. package/dist/tests/collection/index-type.test.d.ts +2 -0
  143. package/dist/tests/collection/index-type.test.d.ts.map +1 -0
  144. package/dist/tests/collection/index-type.test.js +28 -0
  145. package/dist/tests/collection/index-type.test.js.map +1 -0
  146. package/dist/tests/collection/serialize.test.d.ts +2 -0
  147. package/dist/tests/collection/serialize.test.d.ts.map +1 -0
  148. package/dist/tests/collection/serialize.test.js +165 -0
  149. package/dist/tests/collection/serialize.test.js.map +1 -0
  150. package/dist/tests/collection/view.test.d.ts +2 -0
  151. package/dist/tests/collection/view.test.d.ts.map +1 -0
  152. package/dist/tests/collection/view.test.js +66 -0
  153. package/dist/tests/collection/view.test.js.map +1 -0
  154. package/dist/tests/filter/compiler.test.d.ts +2 -0
  155. package/dist/tests/filter/compiler.test.d.ts.map +1 -0
  156. package/dist/tests/filter/compiler.test.js +156 -0
  157. package/dist/tests/filter/compiler.test.js.map +1 -0
  158. package/dist/tests/rule/builder.test.d.ts +2 -0
  159. package/dist/tests/rule/builder.test.d.ts.map +1 -0
  160. package/dist/tests/rule/builder.test.js +290 -0
  161. package/dist/tests/rule/builder.test.js.map +1 -0
  162. package/dist/tsconfig.tsbuildinfo +1 -0
  163. package/package.json +39 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Getter Sethya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,66 @@
1
+ import type { HttpClient } from "@effect/platform";
2
+ import { Effect, MutableRef } from "effect";
3
+ import type { MiraError } from "./errors.js";
4
+ import type { ClientHandler, ExecuteFn } from "./handler.js";
5
+ /**
6
+ * Browser-side authentication helper. Uses a `loggedInRef` to track whether
7
+ * the client has authenticated.
8
+ *
9
+ * In browser mode, the JWT token is handled via cookies — the client only
10
+ * tracks `isLoggedIn()` state. `clear()` sends a POST to `/api/auth/logout`
11
+ * and resets the ref.
12
+ *
13
+ * @example
14
+ * import { createMiraClient } from "@gettersethya/mira-client"
15
+ *
16
+ * const mira = createMiraClient("/") // browser mode by default
17
+ * if (mira.auth.isLoggedIn()) {
18
+ * // user is authenticated
19
+ * }
20
+ * mira.auth.clear() // sends POST /api/auth/logout
21
+ *
22
+ * @see ServerAuth — server-side alternative for SSR environments
23
+ */
24
+ export type BrowserAuth = {
25
+ isLoggedIn(): boolean;
26
+ clear(): void;
27
+ };
28
+ /**
29
+ * Server-side authentication helper. Stores the JWT token in a `MutableRef`
30
+ * for manual management (e.g., during SSR hydration).
31
+ *
32
+ * The `token` getter/setter provides direct access to the raw JWT string.
33
+ * `isValid()` checks the JWT `exp` claim against the current time without
34
+ * making an HTTP request — it only validates expiry, not signature.
35
+ *
36
+ * @example
37
+ * import { createMiraClient } from "@gettersethya/mira-client"
38
+ *
39
+ * const mira = createMiraClient("/", { type: "server" })
40
+ * mira.auth.setToken("eyJ...") // set token from SSR context
41
+ * console.log(mira.auth.isValid()) // true if token is not expired
42
+ * const currentToken = mira.auth.token // "eyJ..."
43
+ * mira.auth.clear() // clears token and file token cache
44
+ *
45
+ * @see BrowserAuth — browser-side alternative
46
+ */
47
+ export type ServerAuth = {
48
+ token: string | null;
49
+ setToken(token: string): void;
50
+ clear(): void;
51
+ isValid(): boolean;
52
+ };
53
+ /**
54
+ * Factory function for `BrowserAuth`. Called internally by `createMiraClient` in browser mode.
55
+ * @internal Use `createMiraClient()` instead of calling this directly
56
+ */
57
+ export declare function makeBrowserAuth(execute: ExecuteFn, makeClientHandler: <T>(effect: Effect.Effect<T, MiraError, HttpClient.HttpClient>) => ClientHandler<T>, loggedInRef: MutableRef.MutableRef<boolean>): BrowserAuth;
58
+ /**
59
+ * Factory function for `ServerAuth`. Called internally by `createMiraClient` in server mode.
60
+ * @internal Use `createMiraClient("/", { type: "server" })` instead of calling this directly
61
+ */
62
+ export declare function makeServerAuth(authTokenRef: MutableRef.MutableRef<string | null>, fileTokenCacheRef: MutableRef.MutableRef<Map<string, {
63
+ token: string;
64
+ expiresAt: number;
65
+ }>>): ServerAuth;
66
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/client/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE5D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,IAAI,OAAO,CAAA;IACrB,KAAK,IAAI,IAAI,CAAA;CACd,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,KAAK,IAAI,IAAI,CAAA;IACb,OAAO,IAAI,OAAO,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,EAClB,iBAAiB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,EACtG,WAAW,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,GAC1C,WAAW,CAWb;AAcD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,EAClD,iBAAiB,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,GAC1F,UAAU,CAoBZ"}
@@ -0,0 +1,60 @@
1
+ import { HttpClientRequest as HCR } from "@effect/platform";
2
+ import { Effect, MutableRef } from "effect";
3
+ /**
4
+ * Factory function for `BrowserAuth`. Called internally by `createMiraClient` in browser mode.
5
+ * @internal Use `createMiraClient()` instead of calling this directly
6
+ */
7
+ export function makeBrowserAuth(execute, makeClientHandler, loggedInRef) {
8
+ return {
9
+ isLoggedIn: () => MutableRef.get(loggedInRef),
10
+ clear: () => {
11
+ const effect = Effect.gen(function* () {
12
+ yield* execute(HCR.post("/api/auth/logout"));
13
+ MutableRef.set(loggedInRef, false);
14
+ });
15
+ void makeClientHandler(effect).raw();
16
+ },
17
+ };
18
+ }
19
+ function decodeJwtExp(token) {
20
+ try {
21
+ const parts = token.split(".");
22
+ if (parts.length !== 3)
23
+ return null;
24
+ const payload = JSON.parse(globalThis.atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
25
+ if (typeof payload.exp === "number")
26
+ return payload.exp;
27
+ return null;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Factory function for `ServerAuth`. Called internally by `createMiraClient` in server mode.
35
+ * @internal Use `createMiraClient("/", { type: "server" })` instead of calling this directly
36
+ */
37
+ export function makeServerAuth(authTokenRef, fileTokenCacheRef) {
38
+ return {
39
+ get token() {
40
+ return MutableRef.get(authTokenRef);
41
+ },
42
+ setToken(token) {
43
+ MutableRef.set(authTokenRef, token);
44
+ },
45
+ clear: () => {
46
+ MutableRef.set(authTokenRef, null);
47
+ MutableRef.set(fileTokenCacheRef, new Map());
48
+ },
49
+ isValid: () => {
50
+ const token = MutableRef.get(authTokenRef);
51
+ if (token === null)
52
+ return false;
53
+ const exp = decodeJwtExp(token);
54
+ if (exp === null)
55
+ return false;
56
+ return Date.now() < exp * 1000;
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/client/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAsD3C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAkB,EAClB,iBAAsG,EACtG,WAA2C;IAE3C,OAAO;QACL,UAAU,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;QAC7C,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBACjC,KAAK,CAAC,CAAC,OAAO,CAAO,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAA;gBAClD,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YACpC,CAAC,CAAC,CAAA;YACF,KAAK,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAA;QACtC,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAC3F,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,GAAG,CAAA;QACvD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAkD,EAClD,iBAA2F;IAE3F,OAAO;QACL,IAAI,KAAK;YACP,OAAO,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACrC,CAAC;QACD,QAAQ,CAAC,KAAa;YACpB,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;QACrC,CAAC;QACD,KAAK,EAAE,GAAS,EAAE;YAChB,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;YAClC,UAAU,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,GAAG,EAAE,CAAC,CAAA;QAC9C,CAAC;QACD,OAAO,EAAE,GAAY,EAAE;YACrB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;YAC1C,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAA;YAChC,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;YAC/B,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAA;YAC9B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAA;QAChC,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,239 @@
1
+ import { MutableRef, Option, Schedule } from "effect";
2
+ import type { AnyCollectionDef, FieldsMap, InferFieldValue, FilterNode, FieldFilterOperand } from "@gettersethya/mira-collection";
3
+ import { MiraError } from "./errors.js";
4
+ import type { ClientHandler, ExecuteFn } from "./handler.js";
5
+ import type { CollectionFileFields, InferMutationInput, InferRecord, RelationKeys, WithExpand } from "./types.js";
6
+ /**
7
+ * Optional retry configuration for collection operations.
8
+ * Wraps an Effect `Schedule` that determines retry behavior when a `MiraError` occurs.
9
+ *
10
+ * If not provided, the operation is not retried. Set at the collection level via
11
+ * `defaultRetryOptions` in `createMiraClient()` or per-call via the `retryOptions` parameter.
12
+ *
13
+ * @example
14
+ * import { Schedule } from "effect"
15
+ *
16
+ * const retry: RetryOptions = {
17
+ * schedule: Schedule.exponential(100) // retry with exponential backoff starting at 100ms
18
+ * }
19
+ *
20
+ * @see createMiraClient — accepts defaultRetryOptions
21
+ * @see CollectionClient — each method accepts retryOptions
22
+ */
23
+ export type RetryOptions = {
24
+ schedule?: Schedule.Schedule<unknown, MiraError, never>;
25
+ };
26
+ type GetListOptions<F extends FieldsMap, E extends ReadonlyArray<string>> = {
27
+ filter?: (f: FilterBuilder<F>) => FilterNode;
28
+ sort?: keyof F & string;
29
+ order?: "asc" | "desc";
30
+ cursor?: number | null;
31
+ limit?: number;
32
+ select?: ReadonlyArray<keyof F & string>;
33
+ expand?: E;
34
+ retryOptions?: RetryOptions;
35
+ };
36
+ type GetOneOptions<F extends FieldsMap, E extends ReadonlyArray<string>> = {
37
+ select?: ReadonlyArray<keyof F & string>;
38
+ expand?: E;
39
+ retryOptions?: RetryOptions;
40
+ };
41
+ /**
42
+ * Typed filter builder used inside `CollectionClient` callback methods.
43
+ * Same shape as `FilterBuilder<F>` in `filter/builder.ts` but re-exported
44
+ * from the client module for convenience.
45
+ *
46
+ * @example
47
+ * const posts = await mira.posts.getList({
48
+ * filter: (f) => f.and(
49
+ * f.field("published").eq(true),
50
+ * f.field("views").gte(100)
51
+ * )
52
+ * }).raw()
53
+ *
54
+ * @see CollectionClient.getList — accepts filter callback
55
+ * @see Filter — untyped filter builder
56
+ */
57
+ export type FilterBuilder<F extends FieldsMap> = {
58
+ field<K extends keyof F & string>(name: K): FieldFilterOperand<InferFieldValue<F[K]>>;
59
+ and(left: FilterNode, right: FilterNode): FilterNode;
60
+ or(left: FilterNode, right: FilterNode): FilterNode;
61
+ not(node: FilterNode): FilterNode;
62
+ };
63
+ /**
64
+ * Client interface for a single collection, providing typed CRUD operations.
65
+ * Created via `makeCollectionClient()` or automatically via `createMiraClient()`.
66
+ *
67
+ * All query methods return `ClientHandler` — call `.raw()` for Promise-based usage
68
+ * or `.toEffect()` for Effect-based usage.
69
+ * All mutation methods return a mutation `ClientHandler` — call `.raw(input)` with
70
+ * the data payload.
71
+ *
72
+ * @typeParam F - The FieldsMap type of the collection
73
+ *
74
+ * @example
75
+ * const posts = mira.posts // inferred as CollectionClient<PostFields>
76
+ * const list = await posts.getList({ sort: "created", order: "desc" }).raw()
77
+ * const one = await posts.getOne("abc123").raw()
78
+ * const created = await posts.create().raw({ title: "hello", body: "world" })
79
+ *
80
+ * @see makeCollectionClient — constructs CollectionClient instances
81
+ * @see ClientHandler — return type of all methods
82
+ */
83
+ export type CollectionClient<F extends FieldsMap> = {
84
+ /**
85
+ * List records with optional filtering, sorting, cursor pagination, and field selection.
86
+ *
87
+ * Returns `{ items, nextCursor }` where `nextCursor` is `null` when there are
88
+ * no more pages. Pagination is cursor-based — iterate by passing the previous
89
+ * response's `nextCursor` as the `cursor` option.
90
+ *
91
+ * @example
92
+ * let cursor: number | null = null
93
+ * do {
94
+ * const { items, nextCursor } = await posts.getList({ cursor, limit: 20 }).raw()
95
+ * cursor = nextCursor
96
+ * } while (cursor !== null)
97
+ *
98
+ * @param options.filter - Optional filter callback using the typed FilterBuilder
99
+ * @param options.sort - Field name to sort by
100
+ * @param options.order - Sort direction: "asc" or "desc" (default: "asc")
101
+ * @param options.cursor - Cursor for pagination (from previous response's nextCursor)
102
+ * @param options.limit - Maximum items per page (server default applies if omitted)
103
+ * @param options.select - Subset of field names to include in the response
104
+ * @param options.expand - Relation field names to expand (fetches related records)
105
+ * @param options.retryOptions - Optional retry schedule
106
+ * @returns ClientHandler for the paginated result
107
+ */
108
+ getList<E extends ReadonlyArray<RelationKeys<F>> = []>(options?: GetListOptions<F, E>): ClientHandler<{
109
+ items: WithExpand<F, E>[];
110
+ nextCursor: number | null;
111
+ }>;
112
+ /**
113
+ * Get the first record matching a filter, or `Option.none()` if none match.
114
+ *
115
+ * **Requires a `filter` callback** — unlike `getList`, the filter is mandatory.
116
+ * Internally calls `getList` with `limit: 1` and extracts the first item.
117
+ *
118
+ * @param filter - Filter callback (required) — use `(f) => f.field("id").eq("x")` etc.
119
+ * @param options.sort - Field name to sort by (determines which is "first")
120
+ * @param options.order - Sort direction
121
+ * @param options.select - Subset of field names to include
122
+ * @param options.expand - Relation field names to expand
123
+ * @param options.retryOptions - Optional retry schedule
124
+ * @returns ClientHandler resolving to Option of the record (None if no match)
125
+ */
126
+ getFirstOrNone<E extends ReadonlyArray<RelationKeys<F>> = []>(filter: (f: FilterBuilder<F>) => FilterNode, options?: Omit<GetListOptions<F, E>, "filter" | "limit" | "cursor">): ClientHandler<Option.Option<WithExpand<F, E>>>;
127
+ /**
128
+ * Fetch all records matching the filter, automatically following pagination.
129
+ * Defaults to `limit: 1000` — override via options if you need a different page size.
130
+ *
131
+ * Unlike `getList` which returns a single page with `nextCursor`,
132
+ * `getFullList` fetches pages internally and returns a flat array.
133
+ *
134
+ * @param options.filter - Optional filter callback
135
+ * @param options.sort - Field name to sort by
136
+ * @param options.order - Sort direction
137
+ * @param options.limit - Page size for internal pagination (default: 1000)
138
+ * @param options.select - Subset of field names to include
139
+ * @param options.expand - Relation field names to expand
140
+ * @param options.retryOptions - Optional retry schedule
141
+ * @returns ClientHandler resolving to a flat array of records
142
+ */
143
+ getFullList<E extends ReadonlyArray<RelationKeys<F>> = []>(options?: Omit<GetListOptions<F, E>, "limit" | "cursor"> & {
144
+ limit?: number;
145
+ }): ClientHandler<WithExpand<F, E>[]>;
146
+ /**
147
+ * Get a single record by its `id`.
148
+ * Returns a 404 `MiraError` if the record does not exist.
149
+ *
150
+ * @param id - The record ID (string UUID)
151
+ * @param options.select - Subset of field names to include
152
+ * @param options.expand - Relation field names to expand
153
+ * @param options.retryOptions - Optional retry schedule
154
+ * @returns ClientHandler resolving to the record
155
+ */
156
+ getOne<E extends ReadonlyArray<RelationKeys<F>> = []>(id: string, options?: GetOneOptions<F, E>): ClientHandler<WithExpand<F, E>>;
157
+ /**
158
+ * Create a new record.
159
+ *
160
+ * When the input contains any `File` or `Blob` values (for file fields), the
161
+ * request is automatically dispatched as `multipart/form-data` instead of JSON.
162
+ *
163
+ * @returns A mutation ClientHandler — call `.raw(input)` with the record data
164
+ */
165
+ create(): ClientHandler<InferRecord<F>, InferMutationInput<F>>;
166
+ /**
167
+ * Update an existing record by ID.
168
+ * Only the fields present in `data` are updated (partial/patch semantics).
169
+ *
170
+ * When `data` contains any `File` or `Blob` values, the request is automatically
171
+ * dispatched as `multipart/form-data`.
172
+ *
173
+ * @returns A mutation ClientHandler — call `.raw({ id, data })`
174
+ */
175
+ update(): ClientHandler<InferRecord<F>, {
176
+ id: string;
177
+ data: Partial<InferMutationInput<F>>;
178
+ }>;
179
+ /**
180
+ * Delete a record by ID.
181
+ * Returns `void` on success. Throws `MiraError` (404) if the record does not exist.
182
+ *
183
+ * @returns A mutation ClientHandler — call `.raw(id)` with the record ID
184
+ */
185
+ delete(): ClientHandler<void, string>;
186
+ /**
187
+ * Authenticate with email and password on an auth collection.
188
+ * Only available on collections defined with `AuthCollection.define()`.
189
+ * On success, stores the returned JWT token for subsequent requests.
190
+ *
191
+ * @example
192
+ * const { token, record } = await mira.users.authWithPassword().raw({
193
+ * email: "user@example.com",
194
+ * password: "secret123"
195
+ * })
196
+ *
197
+ * @returns A mutation ClientHandler — call `.raw({ email, password })`
198
+ */
199
+ authWithPassword?(): ClientHandler<{
200
+ token: string;
201
+ record: InferRecord<F>;
202
+ }, {
203
+ email: string;
204
+ password: string;
205
+ }>;
206
+ /**
207
+ * File field client interfaces for the collection.
208
+ * Provides `.url()` and `.asyncUrl()` methods for constructing file download URLs.
209
+ *
210
+ * @example
211
+ * const url = posts.fields.cover.url(post.id, "cover.jpg")
212
+ */
213
+ fields: CollectionFileFields<F>;
214
+ };
215
+ type MakeCollectionClientParams<F extends FieldsMap> = {
216
+ collectionName: string;
217
+ schema: AnyCollectionDef["schema"];
218
+ fields: F;
219
+ execute: ExecuteFn;
220
+ baseUrl: string;
221
+ authTokenRef: MutableRef.MutableRef<string | null> | null;
222
+ loggedInRef: MutableRef.MutableRef<boolean> | null;
223
+ fileTokenCacheRef: MutableRef.MutableRef<Map<string, {
224
+ token: string;
225
+ expiresAt: number;
226
+ }>>;
227
+ isAuth: boolean;
228
+ defaultRetryOptions?: RetryOptions;
229
+ };
230
+ /**
231
+ * Construct a `CollectionClient<F>` for a given collection definition.
232
+ * This is the internal factory — users should use `createMiraClient()` which
233
+ * handles all wiring (auth, execute, file fields).
234
+ *
235
+ * @internal Use `createMiraClient().collection(def)` or `withCollections()` instead.
236
+ */
237
+ export declare function makeCollectionClient<F extends FieldsMap>(params: MakeCollectionClientParams<F>): CollectionClient<F>;
238
+ export {};
239
+ //# sourceMappingURL=collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/client/collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ import { HttpClientRequest as HCR } from "@effect/platform";
2
+ import { Effect, MutableRef, Option, Schema } from "effect";
3
+ import { Filter, FilterNodeSchema } from "@gettersethya/mira-collection";
4
+ import { MiraError } from "./errors.js";
5
+ import { makeClientHandler as makeHandler, makeMutationHandler } from "./handler.js";
6
+ import { makeFileFields } from "./file.js";
7
+ function toExecuteEffect(reqEffect, execute) {
8
+ return reqEffect.pipe(Effect.flatMap((req) => execute(req)), Effect.catchTag("HttpBodyError", (e) => Effect.fail(new MiraError({ status: 500, body: String(e) }))));
9
+ }
10
+ function hasFileOrBlob(input) {
11
+ return Object.values(input).some((v) => v instanceof Blob);
12
+ }
13
+ function buildFormData(input) {
14
+ const fd = new FormData();
15
+ for (const [key, value] of Object.entries(input)) {
16
+ if (value instanceof Blob) {
17
+ fd.append(key, value);
18
+ }
19
+ else if (value !== null && value !== undefined) {
20
+ fd.append(key, String(value));
21
+ }
22
+ }
23
+ return fd;
24
+ }
25
+ function makeFilterBuilder() {
26
+ return {
27
+ field: (name) => Filter.field(name),
28
+ and: (left, right) => Filter.and(left, right),
29
+ or: (left, right) => Filter.or(left, right),
30
+ not: (node) => Filter.not(node),
31
+ };
32
+ }
33
+ function buildQueryParams(params) {
34
+ const sp = new URLSearchParams();
35
+ for (const [k, v] of Object.entries(params)) {
36
+ if (v !== undefined)
37
+ sp.set(k, v);
38
+ }
39
+ const qs = sp.toString();
40
+ return qs ? `?${qs}` : "";
41
+ }
42
+ /**
43
+ * Construct a `CollectionClient<F>` for a given collection definition.
44
+ * This is the internal factory — users should use `createMiraClient()` which
45
+ * handles all wiring (auth, execute, file fields).
46
+ *
47
+ * @internal Use `createMiraClient().collection(def)` or `withCollections()` instead.
48
+ */
49
+ export function makeCollectionClient(params) {
50
+ const { collectionName, schema, fields, execute, baseUrl, authTokenRef, loggedInRef, fileTokenCacheRef, isAuth, defaultRetryOptions } = params;
51
+ function withRetry(effect, methodOptions) {
52
+ const schedule = methodOptions?.retryOptions?.schedule ?? defaultRetryOptions?.schedule;
53
+ return schedule ? Effect.retry(effect, schedule) : effect;
54
+ }
55
+ const fileFields = makeFileFields({ name: collectionName, fields, schema }, schema, baseUrl, execute, fileTokenCacheRef, makeHandler);
56
+ function getList(options) {
57
+ const filterNode = options?.filter?.(makeFilterBuilder());
58
+ const queryParams = buildQueryParams({
59
+ ...(filterNode ? { filter: Schema.encodeSync(Schema.parseJson(FilterNodeSchema))(filterNode) } : {}),
60
+ ...(options?.sort ? { sort: options.sort } : {}),
61
+ ...(options?.order ? { order: options.order } : {}),
62
+ ...(options?.cursor != null ? { after: String(options.cursor) } : {}),
63
+ ...(options?.limit ? { limit: String(options.limit) } : {}),
64
+ ...(options?.select ? { select: options.select.join(",") } : {}),
65
+ ...(options?.expand ? { expand: options.expand.join(",") } : {}),
66
+ });
67
+ const effect = execute(HCR.get(`/api/collections/${collectionName}${queryParams}`));
68
+ return makeHandler(withRetry(effect, options));
69
+ }
70
+ function getFirstOrNone(filter, options) {
71
+ const effect = getList({ ...options, filter, limit: 1 })
72
+ .toEffect()
73
+ .pipe(Effect.map(({ items }) => Option.fromNullable(items[0] ?? null)));
74
+ return makeHandler(effect);
75
+ }
76
+ function getFullList(options) {
77
+ const effect = getList({ ...options, limit: options?.limit ?? 1000 })
78
+ .toEffect()
79
+ .pipe(Effect.map(({ items }) => items));
80
+ return makeHandler(effect);
81
+ }
82
+ function getOne(id, options) {
83
+ const queryParams = buildQueryParams({
84
+ ...(options?.select ? { select: options.select.join(",") } : {}),
85
+ ...(options?.expand ? { expand: options.expand.join(",") } : {}),
86
+ });
87
+ const effect = execute(HCR.get(`/api/collections/${collectionName}/${id}${queryParams}`));
88
+ return makeHandler(withRetry(effect, options));
89
+ }
90
+ function create() {
91
+ return makeMutationHandler((input) => {
92
+ const reqEffect = hasFileOrBlob(input)
93
+ ? Effect.succeed(HCR.bodyFormData(HCR.post(`/api/collections/${collectionName}`), buildFormData(input)))
94
+ : HCR.bodyJson(HCR.post(`/api/collections/${collectionName}`), input);
95
+ return withRetry(toExecuteEffect(reqEffect, execute));
96
+ });
97
+ }
98
+ function update() {
99
+ return makeMutationHandler(({ id, data }) => {
100
+ const reqEffect = hasFileOrBlob(data)
101
+ ? Effect.succeed(HCR.bodyFormData(HCR.patch(`/api/collections/${collectionName}/${id}`), buildFormData(data)))
102
+ : HCR.bodyJson(HCR.patch(`/api/collections/${collectionName}/${id}`), data);
103
+ return withRetry(toExecuteEffect(reqEffect, execute));
104
+ });
105
+ }
106
+ function deleteFn() {
107
+ return makeMutationHandler((id) => {
108
+ const effect = execute(HCR.del(`/api/collections/${collectionName}/${id}`));
109
+ return withRetry(effect);
110
+ });
111
+ }
112
+ function authWithPassword() {
113
+ return makeMutationHandler(({ email, password }) => withRetry(Effect.gen(function* () {
114
+ const res = yield* toExecuteEffect(HCR.bodyJson(HCR.post(`/api/collections/${collectionName}/auth-with-password`), { email, password }), execute);
115
+ if (authTokenRef !== null) {
116
+ MutableRef.set(authTokenRef, res.token);
117
+ }
118
+ if (loggedInRef !== null) {
119
+ MutableRef.set(loggedInRef, true);
120
+ }
121
+ return res;
122
+ })));
123
+ }
124
+ const client = {
125
+ getList,
126
+ getFirstOrNone,
127
+ getFullList,
128
+ getOne,
129
+ create,
130
+ update,
131
+ delete: deleteFn,
132
+ ...(isAuth ? { authWithPassword } : {}),
133
+ fields: fileFields,
134
+ };
135
+ return client;
136
+ }
137
+ //# sourceMappingURL=collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../../../src/client/collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ declare const MiraError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "MiraError";
3
+ } & Readonly<A>;
4
+ /**
5
+ * Error thrown by `ClientHandler.raw()` when an HTTP request to the Mira server fails.
6
+ *
7
+ * Wraps the HTTP status code and response body. The `status` field corresponds to
8
+ * the HTTP status code (e.g., 404, 403, 422, 0 for network errors). The `body`
9
+ * field contains the server's JSON error response (typically `{ error, message, issues }`).
10
+ *
11
+ * `MiraError` is thrown **directly** from `.raw()` — it is NOT wrapped in `FiberFailure`.
12
+ * In the Effect channel (`toEffect()`), it is available in the error channel and can
13
+ * be caught via `Effect.catchTag("MiraError", ...)`.
14
+ *
15
+ * @example
16
+ * import { createMiraClient, MiraError } from "@gettersethya/mira-client"
17
+ *
18
+ * const mira = createMiraClient("/")
19
+ *
20
+ * try {
21
+ * await mira.posts.getOne("nonexistent").raw()
22
+ * } catch (e) {
23
+ * if (e instanceof MiraError) {
24
+ * console.error(`HTTP ${e.status}:`, e.body)
25
+ * }
26
+ * }
27
+ *
28
+ * @example
29
+ * // In Effect context via toEffect()
30
+ * import { Effect } from "effect"
31
+ *
32
+ * mira.posts.getOne("nonexistent").toEffect().pipe(
33
+ * Effect.catchTag("MiraError", (e) =>
34
+ * Effect.logError(`HTTP ${e.status}: ${JSON.stringify(e.body)}`)
35
+ * )
36
+ * )
37
+ *
38
+ * @see ClientHandler — the interface that throws MiraError from .raw()
39
+ */
40
+ export declare class MiraError extends MiraError_base<{
41
+ readonly status: number;
42
+ readonly body: unknown;
43
+ }> {
44
+ }
45
+ export {};
46
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/client/errors.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB,CAAC;CAAG"}
@@ -0,0 +1,40 @@
1
+ import { Data } from "effect";
2
+ /**
3
+ * Error thrown by `ClientHandler.raw()` when an HTTP request to the Mira server fails.
4
+ *
5
+ * Wraps the HTTP status code and response body. The `status` field corresponds to
6
+ * the HTTP status code (e.g., 404, 403, 422, 0 for network errors). The `body`
7
+ * field contains the server's JSON error response (typically `{ error, message, issues }`).
8
+ *
9
+ * `MiraError` is thrown **directly** from `.raw()` — it is NOT wrapped in `FiberFailure`.
10
+ * In the Effect channel (`toEffect()`), it is available in the error channel and can
11
+ * be caught via `Effect.catchTag("MiraError", ...)`.
12
+ *
13
+ * @example
14
+ * import { createMiraClient, MiraError } from "@gettersethya/mira-client"
15
+ *
16
+ * const mira = createMiraClient("/")
17
+ *
18
+ * try {
19
+ * await mira.posts.getOne("nonexistent").raw()
20
+ * } catch (e) {
21
+ * if (e instanceof MiraError) {
22
+ * console.error(`HTTP ${e.status}:`, e.body)
23
+ * }
24
+ * }
25
+ *
26
+ * @example
27
+ * // In Effect context via toEffect()
28
+ * import { Effect } from "effect"
29
+ *
30
+ * mira.posts.getOne("nonexistent").toEffect().pipe(
31
+ * Effect.catchTag("MiraError", (e) =>
32
+ * Effect.logError(`HTTP ${e.status}: ${JSON.stringify(e.body)}`)
33
+ * )
34
+ * )
35
+ *
36
+ * @see ClientHandler — the interface that throws MiraError from .raw()
37
+ */
38
+ export class MiraError extends Data.TaggedError("MiraError") {
39
+ }
40
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/client/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,OAAO,SAAU,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAGzD;CAAG"}