@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.
- package/LICENSE +21 -0
- package/dist/src/client/auth.d.ts +66 -0
- package/dist/src/client/auth.d.ts.map +1 -0
- package/dist/src/client/auth.js +60 -0
- package/dist/src/client/auth.js.map +1 -0
- package/dist/src/client/collection.d.ts +239 -0
- package/dist/src/client/collection.d.ts.map +1 -0
- package/dist/src/client/collection.js +137 -0
- package/dist/src/client/collection.js.map +1 -0
- package/dist/src/client/errors.d.ts +46 -0
- package/dist/src/client/errors.d.ts.map +1 -0
- package/dist/src/client/errors.js +40 -0
- package/dist/src/client/errors.js.map +1 -0
- package/dist/src/client/factory.d.ts +76 -0
- package/dist/src/client/factory.d.ts.map +1 -0
- package/dist/src/client/factory.js +106 -0
- package/dist/src/client/factory.js.map +1 -0
- package/dist/src/client/file.d.ts +116 -0
- package/dist/src/client/file.d.ts.map +1 -0
- package/dist/src/client/file.js +99 -0
- package/dist/src/client/file.js.map +1 -0
- package/dist/src/client/handler.d.ts +92 -0
- package/dist/src/client/handler.d.ts.map +1 -0
- package/dist/src/client/handler.js +62 -0
- package/dist/src/client/handler.js.map +1 -0
- package/dist/src/client/index.d.ts +11 -0
- package/dist/src/client/index.d.ts.map +1 -0
- package/dist/src/client/index.js +6 -0
- package/dist/src/client/index.js.map +1 -0
- package/dist/src/client/types.d.ts +138 -0
- package/dist/src/client/types.d.ts.map +1 -0
- package/dist/src/client/types.js +2 -0
- package/dist/src/client/types.js.map +1 -0
- package/dist/src/collection/auth.d.ts +79 -0
- package/dist/src/collection/auth.d.ts.map +1 -0
- package/dist/src/collection/auth.js +50 -0
- package/dist/src/collection/auth.js.map +1 -0
- package/dist/src/collection/base.d.ts +64 -0
- package/dist/src/collection/base.d.ts.map +1 -0
- package/dist/src/collection/base.js +40 -0
- package/dist/src/collection/base.js.map +1 -0
- package/dist/src/collection/bytes.d.ts +51 -0
- package/dist/src/collection/bytes.d.ts.map +1 -0
- package/dist/src/collection/bytes.js +51 -0
- package/dist/src/collection/bytes.js.map +1 -0
- package/dist/src/collection/errors.d.ts +29 -0
- package/dist/src/collection/errors.d.ts.map +1 -0
- package/dist/src/collection/errors.js +23 -0
- package/dist/src/collection/errors.js.map +1 -0
- package/dist/src/collection/field.d.ts +300 -0
- package/dist/src/collection/field.d.ts.map +1 -0
- package/dist/src/collection/field.js +175 -0
- package/dist/src/collection/field.js.map +1 -0
- package/dist/src/collection/index-builder.d.ts +59 -0
- package/dist/src/collection/index-builder.d.ts.map +1 -0
- package/dist/src/collection/index-builder.js +43 -0
- package/dist/src/collection/index-builder.js.map +1 -0
- package/dist/src/collection/index.d.ts +22 -0
- package/dist/src/collection/index.d.ts.map +1 -0
- package/dist/src/collection/index.js +21 -0
- package/dist/src/collection/index.js.map +1 -0
- package/dist/src/collection/serialize.d.ts +24 -0
- package/dist/src/collection/serialize.d.ts.map +1 -0
- package/dist/src/collection/serialize.js +127 -0
- package/dist/src/collection/serialize.js.map +1 -0
- package/dist/src/collection/types.d.ts +119 -0
- package/dist/src/collection/types.d.ts.map +1 -0
- package/dist/src/collection/types.js +2 -0
- package/dist/src/collection/types.js.map +1 -0
- package/dist/src/collection/view.d.ts +57 -0
- package/dist/src/collection/view.d.ts.map +1 -0
- package/dist/src/collection/view.js +49 -0
- package/dist/src/collection/view.js.map +1 -0
- package/dist/src/filter/builder.d.ts +127 -0
- package/dist/src/filter/builder.d.ts.map +1 -0
- package/dist/src/filter/builder.js +72 -0
- package/dist/src/filter/builder.js.map +1 -0
- package/dist/src/filter/compiler.d.ts +48 -0
- package/dist/src/filter/compiler.d.ts.map +1 -0
- package/dist/src/filter/compiler.js +132 -0
- package/dist/src/filter/compiler.js.map +1 -0
- package/dist/src/filter/index.d.ts +6 -0
- package/dist/src/filter/index.d.ts.map +1 -0
- package/dist/src/filter/index.js +4 -0
- package/dist/src/filter/index.js.map +1 -0
- package/dist/src/filter/types.d.ts +96 -0
- package/dist/src/filter/types.d.ts.map +1 -0
- package/dist/src/filter/types.js +44 -0
- package/dist/src/filter/types.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/rule/builder.d.ts +97 -0
- package/dist/src/rule/builder.d.ts.map +1 -0
- package/dist/src/rule/builder.js +126 -0
- package/dist/src/rule/builder.js.map +1 -0
- package/dist/src/rule/index.d.ts +3 -0
- package/dist/src/rule/index.d.ts.map +1 -0
- package/dist/src/rule/index.js +3 -0
- package/dist/src/rule/index.js.map +1 -0
- package/dist/src/rule/types.d.ts +129 -0
- package/dist/src/rule/types.d.ts.map +1 -0
- package/dist/src/rule/types.js +2 -0
- package/dist/src/rule/types.js.map +1 -0
- package/dist/tests/client/auth.test.d.ts +2 -0
- package/dist/tests/client/auth.test.d.ts.map +1 -0
- package/dist/tests/client/auth.test.js +67 -0
- package/dist/tests/client/auth.test.js.map +1 -0
- package/dist/tests/client/collection.test.d.ts +2 -0
- package/dist/tests/client/collection.test.d.ts.map +1 -0
- package/dist/tests/client/collection.test.js +543 -0
- package/dist/tests/client/collection.test.js.map +1 -0
- package/dist/tests/client/file.test.d.ts +2 -0
- package/dist/tests/client/file.test.d.ts.map +1 -0
- package/dist/tests/client/file.test.js +21 -0
- package/dist/tests/client/file.test.js.map +1 -0
- package/dist/tests/client/handler.test.d.ts +2 -0
- package/dist/tests/client/handler.test.d.ts.map +1 -0
- package/dist/tests/client/handler.test.js +24 -0
- package/dist/tests/client/handler.test.js.map +1 -0
- package/dist/tests/client/types.test.d.ts +2 -0
- package/dist/tests/client/types.test.d.ts.map +1 -0
- package/dist/tests/client/types.test.js +168 -0
- package/dist/tests/client/types.test.js.map +1 -0
- package/dist/tests/collection/auth.test.d.ts +2 -0
- package/dist/tests/collection/auth.test.d.ts.map +1 -0
- package/dist/tests/collection/auth.test.js +44 -0
- package/dist/tests/collection/auth.test.js.map +1 -0
- package/dist/tests/collection/base.test.d.ts +2 -0
- package/dist/tests/collection/base.test.d.ts.map +1 -0
- package/dist/tests/collection/base.test.js +70 -0
- package/dist/tests/collection/base.test.js.map +1 -0
- package/dist/tests/collection/bytes.test.d.ts +2 -0
- package/dist/tests/collection/bytes.test.d.ts.map +1 -0
- package/dist/tests/collection/bytes.test.js +9 -0
- package/dist/tests/collection/bytes.test.js.map +1 -0
- package/dist/tests/collection/field.test.d.ts +2 -0
- package/dist/tests/collection/field.test.d.ts.map +1 -0
- package/dist/tests/collection/field.test.js +140 -0
- package/dist/tests/collection/field.test.js.map +1 -0
- package/dist/tests/collection/index-type.test.d.ts +2 -0
- package/dist/tests/collection/index-type.test.d.ts.map +1 -0
- package/dist/tests/collection/index-type.test.js +28 -0
- package/dist/tests/collection/index-type.test.js.map +1 -0
- package/dist/tests/collection/serialize.test.d.ts +2 -0
- package/dist/tests/collection/serialize.test.d.ts.map +1 -0
- package/dist/tests/collection/serialize.test.js +165 -0
- package/dist/tests/collection/serialize.test.js.map +1 -0
- package/dist/tests/collection/view.test.d.ts +2 -0
- package/dist/tests/collection/view.test.d.ts.map +1 -0
- package/dist/tests/collection/view.test.js +66 -0
- package/dist/tests/collection/view.test.js.map +1 -0
- package/dist/tests/filter/compiler.test.d.ts +2 -0
- package/dist/tests/filter/compiler.test.d.ts.map +1 -0
- package/dist/tests/filter/compiler.test.js +156 -0
- package/dist/tests/filter/compiler.test.js.map +1 -0
- package/dist/tests/rule/builder.test.d.ts +2 -0
- package/dist/tests/rule/builder.test.d.ts.map +1 -0
- package/dist/tests/rule/builder.test.js +290 -0
- package/dist/tests/rule/builder.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- 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":"AACA,OAAO,EAAE,iBAAiB,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAA;AAErE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EAAE,iBAAiB,IAAI,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAK1C,SAAS,eAAe,CACtB,SAA0B,EAC1B,OAAkB;IAElB,OAAO,SAAS,CAAC,IAAI,CACnB,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAI,GAAG,CAAC,CAAC,EACxC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CACrC,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAC7D,CACF,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,IAAI,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAA;IACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YAC1B,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACjD,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AA6DD,SAAS,iBAAiB;IACxB,OAAO;QACL,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAC3C,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;QAC7C,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;QAC3C,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KAChC,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,MAA0C;IAClE,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAA;IAChC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,SAAS;YAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACnC,CAAC;IACD,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAA;IACxB,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AAC3B,CAAC;AA4KD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAqC;IAErC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,CAAA;IAE9I,SAAS,SAAS,CAChB,MAA0D,EAC1D,aAA+C;QAE/C,MAAM,QAAQ,GAAG,aAAa,EAAE,YAAY,EAAE,QAAQ,IAAI,mBAAmB,EAAE,QAAQ,CAAA;QACvF,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IAC3D,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,CAC/B,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,EACxC,MAAM,EACN,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,WAAW,CACZ,CAAA;IAED,SAAS,OAAO,CACd,OAA8B;QAE9B,MAAM,UAAU,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,iBAAiB,EAAK,CAAC,CAAA;QAC5D,MAAM,WAAW,GAAG,gBAAgB,CAAC;YACnC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,CAAC,GAAG,CAAC,oBAAoB,cAAc,GAAG,WAAW,EAAE,CAAC,CAC5D,CAAA;QACD,OAAO,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAChD,CAAC;IAED,SAAS,cAAc,CACrB,MAA2C,EAC3C,OAAmE;QAEnE,MAAM,MAAM,GAAG,OAAO,CAAI,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;aACxD,QAAQ,EAAE;aACV,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;QACzE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,SAAS,WAAW,CAClB,OAA6E;QAE7E,MAAM,MAAM,GAAG,OAAO,CAAI,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;aACrE,QAAQ,EAAE;aACV,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;QACzC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,SAAS,MAAM,CACb,EAAU,EACV,OAA6B;QAE7B,MAAM,WAAW,GAAG,gBAAgB,CAAC;YACnC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,CAAC,GAAG,CAAC,oBAAoB,cAAc,IAAI,EAAE,GAAG,WAAW,EAAE,CAAC,CAClE,CAAA;QACD,OAAO,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAChD,CAAC;IAED,SAAS,MAAM;QACb,OAAO,mBAAmB,CAAwC,CAAC,KAAK,EAAE,EAAE;YAC1E,MAAM,SAAS,GAAoB,aAAa,CAAC,KAAK,CAAC;gBACrD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,cAAc,EAAE,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;gBACxG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,cAAc,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;YACvE,OAAO,SAAS,CAAC,eAAe,CAAiB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;QACvE,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,SAAS,MAAM;QACb,OAAO,mBAAmB,CAAuE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAChH,MAAM,SAAS,GAAoB,aAAa,CAAC,IAAI,CAAC;gBACpD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,cAAc,IAAI,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9G,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,cAAc,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;YAC7E,OAAO,SAAS,CAAC,eAAe,CAAiB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;QACvE,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,SAAS,QAAQ;QACf,OAAO,mBAAmB,CAAe,CAAC,EAAE,EAAE,EAAE;YAC9C,MAAM,MAAM,GAAG,OAAO,CAAO,GAAG,CAAC,GAAG,CAAC,oBAAoB,cAAc,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;YACjF,OAAO,SAAS,CAAC,MAAM,CAAC,CAAA;QAC1B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,SAAS,gBAAgB;QACvB,OAAO,mBAAmB,CACxB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CACtB,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,eAAe,CAChC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,cAAc,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EACpG,OAAO,CACR,CAAA;YACD,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;gBAC1B,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;YACzC,CAAC;YACD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;YACnC,CAAC;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,CAAC,CAAC,CACN,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAwB;QAClC,OAAO;QACP,cAAc;QACd,WAAW;QACX,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM,EAAE,QAAQ;QAChB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,EAAE,UAAU;KACnB,CAAA;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -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"}
|