@gettersethya/mira-client 0.1.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/dist/src/client/auth.d.ts +73 -0
  4. package/dist/src/client/auth.d.ts.map +1 -0
  5. package/dist/src/client/auth.js +72 -0
  6. package/dist/src/client/auth.js.map +1 -0
  7. package/dist/src/client/collection.d.ts +239 -0
  8. package/dist/src/client/collection.d.ts.map +1 -0
  9. package/dist/src/client/collection.js +137 -0
  10. package/dist/src/client/collection.js.map +1 -0
  11. package/dist/src/client/errors.d.ts +46 -0
  12. package/dist/src/client/errors.d.ts.map +1 -0
  13. package/dist/src/client/errors.js +40 -0
  14. package/dist/src/client/errors.js.map +1 -0
  15. package/dist/src/client/factory.d.ts +78 -0
  16. package/dist/src/client/factory.d.ts.map +1 -0
  17. package/dist/src/client/factory.js +108 -0
  18. package/dist/src/client/factory.js.map +1 -0
  19. package/dist/src/client/file.d.ts +116 -0
  20. package/dist/src/client/file.d.ts.map +1 -0
  21. package/dist/src/client/file.js +99 -0
  22. package/dist/src/client/file.js.map +1 -0
  23. package/dist/src/client/handler.d.ts +92 -0
  24. package/dist/src/client/handler.d.ts.map +1 -0
  25. package/dist/src/client/handler.js +62 -0
  26. package/dist/src/client/handler.js.map +1 -0
  27. package/dist/src/client/index.d.ts +13 -0
  28. package/dist/src/client/index.d.ts.map +1 -0
  29. package/dist/src/client/index.js +7 -0
  30. package/dist/src/client/index.js.map +1 -0
  31. package/dist/src/client/telemetry.d.ts +50 -0
  32. package/dist/src/client/telemetry.d.ts.map +1 -0
  33. package/dist/src/client/telemetry.js +32 -0
  34. package/dist/src/client/telemetry.js.map +1 -0
  35. package/dist/src/client/types.d.ts +137 -0
  36. package/dist/src/client/types.d.ts.map +1 -0
  37. package/dist/src/client/types.js +2 -0
  38. package/dist/src/client/types.js.map +1 -0
  39. package/dist/src/collection/auth.d.ts +79 -0
  40. package/dist/src/collection/auth.d.ts.map +1 -0
  41. package/dist/src/collection/auth.js +50 -0
  42. package/dist/src/collection/auth.js.map +1 -0
  43. package/dist/src/collection/base.d.ts +64 -0
  44. package/dist/src/collection/base.d.ts.map +1 -0
  45. package/dist/src/collection/base.js +40 -0
  46. package/dist/src/collection/base.js.map +1 -0
  47. package/dist/src/collection/bytes.d.ts +51 -0
  48. package/dist/src/collection/bytes.d.ts.map +1 -0
  49. package/dist/src/collection/bytes.js +51 -0
  50. package/dist/src/collection/bytes.js.map +1 -0
  51. package/dist/src/collection/errors.d.ts +29 -0
  52. package/dist/src/collection/errors.d.ts.map +1 -0
  53. package/dist/src/collection/errors.js +23 -0
  54. package/dist/src/collection/errors.js.map +1 -0
  55. package/dist/src/collection/field.d.ts +300 -0
  56. package/dist/src/collection/field.d.ts.map +1 -0
  57. package/dist/src/collection/field.js +175 -0
  58. package/dist/src/collection/field.js.map +1 -0
  59. package/dist/src/collection/index-builder.d.ts +59 -0
  60. package/dist/src/collection/index-builder.d.ts.map +1 -0
  61. package/dist/src/collection/index-builder.js +43 -0
  62. package/dist/src/collection/index-builder.js.map +1 -0
  63. package/dist/src/collection/index.d.ts +22 -0
  64. package/dist/src/collection/index.d.ts.map +1 -0
  65. package/dist/src/collection/index.js +21 -0
  66. package/dist/src/collection/index.js.map +1 -0
  67. package/dist/src/collection/serialize.d.ts +24 -0
  68. package/dist/src/collection/serialize.d.ts.map +1 -0
  69. package/dist/src/collection/serialize.js +127 -0
  70. package/dist/src/collection/serialize.js.map +1 -0
  71. package/dist/src/collection/types.d.ts +119 -0
  72. package/dist/src/collection/types.d.ts.map +1 -0
  73. package/dist/src/collection/types.js +2 -0
  74. package/dist/src/collection/types.js.map +1 -0
  75. package/dist/src/collection/view.d.ts +57 -0
  76. package/dist/src/collection/view.d.ts.map +1 -0
  77. package/dist/src/collection/view.js +49 -0
  78. package/dist/src/collection/view.js.map +1 -0
  79. package/dist/src/filter/builder.d.ts +127 -0
  80. package/dist/src/filter/builder.d.ts.map +1 -0
  81. package/dist/src/filter/builder.js +72 -0
  82. package/dist/src/filter/builder.js.map +1 -0
  83. package/dist/src/filter/compiler.d.ts +48 -0
  84. package/dist/src/filter/compiler.d.ts.map +1 -0
  85. package/dist/src/filter/compiler.js +132 -0
  86. package/dist/src/filter/compiler.js.map +1 -0
  87. package/dist/src/filter/index.d.ts +6 -0
  88. package/dist/src/filter/index.d.ts.map +1 -0
  89. package/dist/src/filter/index.js +4 -0
  90. package/dist/src/filter/index.js.map +1 -0
  91. package/dist/src/filter/types.d.ts +96 -0
  92. package/dist/src/filter/types.d.ts.map +1 -0
  93. package/dist/src/filter/types.js +44 -0
  94. package/dist/src/filter/types.js.map +1 -0
  95. package/dist/src/index.d.ts +3 -0
  96. package/dist/src/index.d.ts.map +1 -0
  97. package/dist/src/index.js +3 -0
  98. package/dist/src/index.js.map +1 -0
  99. package/dist/src/rule/builder.d.ts +97 -0
  100. package/dist/src/rule/builder.d.ts.map +1 -0
  101. package/dist/src/rule/builder.js +126 -0
  102. package/dist/src/rule/builder.js.map +1 -0
  103. package/dist/src/rule/index.d.ts +3 -0
  104. package/dist/src/rule/index.d.ts.map +1 -0
  105. package/dist/src/rule/index.js +3 -0
  106. package/dist/src/rule/index.js.map +1 -0
  107. package/dist/src/rule/types.d.ts +129 -0
  108. package/dist/src/rule/types.d.ts.map +1 -0
  109. package/dist/src/rule/types.js +2 -0
  110. package/dist/src/rule/types.js.map +1 -0
  111. package/dist/tests/client/auth.test.d.ts +2 -0
  112. package/dist/tests/client/auth.test.d.ts.map +1 -0
  113. package/dist/tests/client/auth.test.js +67 -0
  114. package/dist/tests/client/auth.test.js.map +1 -0
  115. package/dist/tests/client/collection.test.d.ts +2 -0
  116. package/dist/tests/client/collection.test.d.ts.map +1 -0
  117. package/dist/tests/client/collection.test.js +593 -0
  118. package/dist/tests/client/collection.test.js.map +1 -0
  119. package/dist/tests/client/file.test.d.ts +2 -0
  120. package/dist/tests/client/file.test.d.ts.map +1 -0
  121. package/dist/tests/client/file.test.js +21 -0
  122. package/dist/tests/client/file.test.js.map +1 -0
  123. package/dist/tests/client/handler.test.d.ts +2 -0
  124. package/dist/tests/client/handler.test.d.ts.map +1 -0
  125. package/dist/tests/client/handler.test.js +24 -0
  126. package/dist/tests/client/handler.test.js.map +1 -0
  127. package/dist/tests/client/types.test.d.ts +2 -0
  128. package/dist/tests/client/types.test.d.ts.map +1 -0
  129. package/dist/tests/client/types.test.js +168 -0
  130. package/dist/tests/client/types.test.js.map +1 -0
  131. package/dist/tests/collection/auth.test.d.ts +2 -0
  132. package/dist/tests/collection/auth.test.d.ts.map +1 -0
  133. package/dist/tests/collection/auth.test.js +44 -0
  134. package/dist/tests/collection/auth.test.js.map +1 -0
  135. package/dist/tests/collection/base.test.d.ts +2 -0
  136. package/dist/tests/collection/base.test.d.ts.map +1 -0
  137. package/dist/tests/collection/base.test.js +70 -0
  138. package/dist/tests/collection/base.test.js.map +1 -0
  139. package/dist/tests/collection/bytes.test.d.ts +2 -0
  140. package/dist/tests/collection/bytes.test.d.ts.map +1 -0
  141. package/dist/tests/collection/bytes.test.js +9 -0
  142. package/dist/tests/collection/bytes.test.js.map +1 -0
  143. package/dist/tests/collection/field.test.d.ts +2 -0
  144. package/dist/tests/collection/field.test.d.ts.map +1 -0
  145. package/dist/tests/collection/field.test.js +140 -0
  146. package/dist/tests/collection/field.test.js.map +1 -0
  147. package/dist/tests/collection/index-type.test.d.ts +2 -0
  148. package/dist/tests/collection/index-type.test.d.ts.map +1 -0
  149. package/dist/tests/collection/index-type.test.js +28 -0
  150. package/dist/tests/collection/index-type.test.js.map +1 -0
  151. package/dist/tests/collection/serialize.test.d.ts +2 -0
  152. package/dist/tests/collection/serialize.test.d.ts.map +1 -0
  153. package/dist/tests/collection/serialize.test.js +165 -0
  154. package/dist/tests/collection/serialize.test.js.map +1 -0
  155. package/dist/tests/collection/view.test.d.ts +2 -0
  156. package/dist/tests/collection/view.test.d.ts.map +1 -0
  157. package/dist/tests/collection/view.test.js +66 -0
  158. package/dist/tests/collection/view.test.js.map +1 -0
  159. package/dist/tests/filter/compiler.test.d.ts +2 -0
  160. package/dist/tests/filter/compiler.test.d.ts.map +1 -0
  161. package/dist/tests/filter/compiler.test.js +156 -0
  162. package/dist/tests/filter/compiler.test.js.map +1 -0
  163. package/dist/tests/rule/builder.test.d.ts +2 -0
  164. package/dist/tests/rule/builder.test.d.ts.map +1 -0
  165. package/dist/tests/rule/builder.test.js +290 -0
  166. package/dist/tests/rule/builder.test.js.map +1 -0
  167. package/dist/tsconfig.tsbuildinfo +1 -0
  168. 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.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # @gettersethya/mira-client
2
+
3
+ > **Early pre-alpha.** Breaking changes may occur without notice.
4
+
5
+ Type-safe client SDK for [Mira](https://github.com/gettersethya/mira). Works in the browser and Node.js (SSR). Every operation returns a handler with both a Promise interface (`.raw()`) and an Effect interface (`.toEffect()`).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @gettersethya/mira-client @gettersethya/mira-collection effect
11
+ # or
12
+ pnpm add @gettersethya/mira-client @gettersethya/mira-collection effect
13
+ ```
14
+
15
+ ## Setup
16
+
17
+ ```typescript
18
+ import { createMiraClient } from "@gettersethya/mira-client"
19
+ import { Posts, Users } from "./collections.js"
20
+
21
+ // Browser — token stored automatically in a cookie
22
+ const mira = createMiraClient("/").withCollections({ posts: Posts, users: Users })
23
+
24
+ // Server — token managed manually
25
+ const mira = createMiraClient("http://localhost:3000", { type: "server" })
26
+ .withCollections({ posts: Posts, users: Users })
27
+ ```
28
+
29
+ ## Queries
30
+
31
+ ```typescript
32
+ // Paginated list — returns { items, nextCursor }
33
+ const { items, nextCursor } = await mira.posts.getList({
34
+ filter: (f) => f.field("published").eq(true),
35
+ sort: "created",
36
+ order: "desc",
37
+ limit: 10,
38
+ cursor: null,
39
+ expand: ["authorId"],
40
+ select: ["id", "title", "authorId"],
41
+ }).raw()
42
+
43
+ // Single record by id
44
+ const post = await mira.posts.getOne("post-id").raw()
45
+
46
+ // First match or nothing (returns Option<T>)
47
+ const latest = await mira.posts.getFirstOrNone({
48
+ filter: (f) => f.field("published").eq(true),
49
+ sort: "created",
50
+ order: "desc",
51
+ }).raw()
52
+
53
+ // All records as a flat array (no pagination)
54
+ const all = await mira.posts.getFullList({ limit: 5000 }).raw()
55
+ ```
56
+
57
+ ## Mutations
58
+
59
+ ```typescript
60
+ // Create
61
+ const post = await mira.posts.create().raw({ title: "Hello", published: false })
62
+
63
+ // Create with file upload — pass File or Blob for file fields
64
+ const post = await mira.posts.create().raw({
65
+ title: "With Image",
66
+ thumbnail: new File([bytes], "thumb.png", { type: "image/png" }),
67
+ })
68
+
69
+ // Update
70
+ const updated = await mira.posts.update().raw(["post-id", { title: "Updated" }])
71
+
72
+ // Delete
73
+ await mira.posts.delete().raw("post-id")
74
+ ```
75
+
76
+ ## Authentication
77
+
78
+ ```typescript
79
+ // Login — token stored automatically (browser) or set manually (server)
80
+ const { token, record } = await mira.users.authWithPassword().raw({
81
+ email: "user@example.com",
82
+ password: "password123",
83
+ })
84
+
85
+ // Server: set the token after login
86
+ mira.auth.setToken(token)
87
+
88
+ // Check login state
89
+ mira.auth.loggedIn() // boolean
90
+
91
+ // Logout
92
+ mira.auth.logout()
93
+ ```
94
+
95
+ ## Effect-based usage
96
+
97
+ Every handler exposes `.toEffect()` for use inside Effect pipelines.
98
+
99
+ ```typescript
100
+ import { Effect } from "effect"
101
+
102
+ const effect = mira.posts.getList({ limit: 10 }).toEffect()
103
+ // Effect.Effect<{ items: Post[], nextCursor: number | null }, MiraError, HttpClient>
104
+
105
+ Effect.gen(function* () {
106
+ const { items } = yield* mira.posts.getList({ limit: 10 }).toEffect()
107
+ const post = yield* mira.posts.getOne("post-id").toEffect()
108
+ })
109
+ ```
110
+
111
+ ## File URLs
112
+
113
+ ```typescript
114
+ import { buildFileUrl } from "@gettersethya/mira-client"
115
+
116
+ // Public file
117
+ const url = buildFileUrl("posts", postId, "thumb.png")
118
+
119
+ // Protected file — request a short-lived token first
120
+ const res = await fetch("/api/files/token", {
121
+ method: "POST",
122
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
123
+ body: JSON.stringify({ collection: "posts" }),
124
+ })
125
+ const { token: fileToken } = await res.json()
126
+ const url = `${buildFileUrl("posts", postId, "thumb.png")}?token=${fileToken}`
127
+ ```
128
+
129
+ ## Type inference
130
+
131
+ ```typescript
132
+ import type { InferRecord, InferCreateInput } from "@gettersethya/mira-client"
133
+
134
+ type Post = InferRecord<typeof Posts> // full record with system fields
135
+ type NewPost = InferCreateInput<typeof Posts> // creation input, no system fields
136
+ ```
137
+
138
+ ## More
139
+
140
+ See the [Mira root README](https://github.com/gettersethya/mira) for full documentation.
@@ -0,0 +1,73 @@
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.
7
+ *
8
+ * The server sets an HttpOnly cookie (`mira_token`) on successful login. The
9
+ * browser sends it automatically on every same-origin request — the client
10
+ * never reads or writes it directly.
11
+ *
12
+ * Because the cookie is HttpOnly, the client cannot tell on page load whether
13
+ * a session exists. Call `refresh()` once on app startup to re-validate the
14
+ * cookie against the server and restore `isLoggedIn()` state.
15
+ *
16
+ * `clear()` calls `POST /api/auth/logout` to clear the cookie server-side,
17
+ * then resets the in-memory login flag.
18
+ *
19
+ * @see ServerAuth — server-side alternative for SSR environments
20
+ */
21
+ export type BrowserAuth = {
22
+ /** True if the user logged in during this page session or `refresh()` confirmed a valid cookie. */
23
+ isLoggedIn(): boolean;
24
+ /**
25
+ * Calls `GET /api/auth/me` to check whether a valid `mira_token` cookie exists.
26
+ * Sets the in-memory login flag to match the server's answer.
27
+ * Call this once on app startup to restore login state after a page reload.
28
+ *
29
+ * @returns true if a valid session exists, false otherwise
30
+ */
31
+ refresh(): Promise<boolean>;
32
+ /** Calls `POST /api/auth/logout` to clear the server cookie, then resets the login flag. */
33
+ clear(): void;
34
+ };
35
+ /**
36
+ * Server-side authentication helper. Stores the JWT token in a `MutableRef`
37
+ * for manual management (e.g., during SSR hydration).
38
+ *
39
+ * The `token` getter/setter provides direct access to the raw JWT string.
40
+ * `isValid()` checks the JWT `exp` claim against the current time without
41
+ * making an HTTP request — it only validates expiry, not signature.
42
+ *
43
+ * @example
44
+ * import { createMiraClient } from "@gettersethya/mira-client"
45
+ *
46
+ * const mira = createMiraClient("/", { type: "server" })
47
+ * mira.auth.setToken("eyJ...") // set token from SSR context
48
+ * console.log(mira.auth.isValid()) // true if token is not expired
49
+ * const currentToken = mira.auth.token // "eyJ..."
50
+ * mira.auth.clear() // clears token and file token cache
51
+ *
52
+ * @see BrowserAuth — browser-side alternative
53
+ */
54
+ export type ServerAuth = {
55
+ token: string | null;
56
+ setToken(token: string): void;
57
+ clear(): void;
58
+ isValid(): boolean;
59
+ };
60
+ /**
61
+ * Factory function for `BrowserAuth`. Called internally by `createMiraClient` in browser mode.
62
+ * @internal Use `createMiraClient()` instead of calling this directly
63
+ */
64
+ export declare function makeBrowserAuth(execute: ExecuteFn, makeClientHandler: <T>(effect: Effect.Effect<T, MiraError, HttpClient.HttpClient>) => ClientHandler<T>, loggedInRef: MutableRef.MutableRef<boolean>): BrowserAuth;
65
+ /**
66
+ * Factory function for `ServerAuth`. Called internally by `createMiraClient` in server mode.
67
+ * @internal Use `createMiraClient("/", { type: "server" })` instead of calling this directly
68
+ */
69
+ export declare function makeServerAuth(authTokenRef: MutableRef.MutableRef<string | null>, fileTokenCacheRef: MutableRef.MutableRef<Map<string, {
70
+ token: string;
71
+ expiresAt: number;
72
+ }>>): ServerAuth;
73
+ //# 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;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,mGAAmG;IACnG,UAAU,IAAI,OAAO,CAAA;IACrB;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3B,4FAA4F;IAC5F,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,CA0Bb;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,72 @@
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
+ refresh: async () => {
11
+ try {
12
+ const effect = execute(HCR.get("/api/auth/me"));
13
+ await makeClientHandler(effect).raw();
14
+ MutableRef.set(loggedInRef, true);
15
+ return true;
16
+ }
17
+ catch {
18
+ MutableRef.set(loggedInRef, false);
19
+ return false;
20
+ }
21
+ },
22
+ clear: () => {
23
+ const effect = Effect.gen(function* () {
24
+ yield* execute(HCR.post("/api/auth/logout"));
25
+ MutableRef.set(loggedInRef, false);
26
+ });
27
+ void makeClientHandler(effect).raw();
28
+ },
29
+ };
30
+ }
31
+ function decodeJwtExp(token) {
32
+ try {
33
+ const parts = token.split(".");
34
+ if (parts.length !== 3)
35
+ return null;
36
+ const payload = JSON.parse(globalThis.atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
37
+ if (typeof payload.exp === "number")
38
+ return payload.exp;
39
+ return null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /**
46
+ * Factory function for `ServerAuth`. Called internally by `createMiraClient` in server mode.
47
+ * @internal Use `createMiraClient("/", { type: "server" })` instead of calling this directly
48
+ */
49
+ export function makeServerAuth(authTokenRef, fileTokenCacheRef) {
50
+ return {
51
+ get token() {
52
+ return MutableRef.get(authTokenRef);
53
+ },
54
+ setToken(token) {
55
+ MutableRef.set(authTokenRef, token);
56
+ },
57
+ clear: () => {
58
+ MutableRef.set(authTokenRef, null);
59
+ MutableRef.set(fileTokenCacheRef, new Map());
60
+ },
61
+ isValid: () => {
62
+ const token = MutableRef.get(authTokenRef);
63
+ if (token === null)
64
+ return false;
65
+ const exp = decodeJwtExp(token);
66
+ if (exp === null)
67
+ return false;
68
+ return Date.now() < exp * 1000;
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/client/auth.ts"],"names":[],"mappings":"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"}
@@ -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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"}