@gettersethya/mira-client 0.1.0-alpha.2 → 0.1.0-alpha.3

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 (2) hide show
  1. package/README.md +140 -0
  2. package/package.json +2 -2
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gettersethya/mira-client",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "type": "module",
5
5
  "description": "Collection definitions and client SDK for Mira",
6
6
  "author": "Getter Sethya",
@@ -15,7 +15,7 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "@gettersethya/mira-collection": "0.1.0-alpha.2"
18
+ "@gettersethya/mira-collection": "0.1.0-alpha.3"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "effect": ">=3.21"