@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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { AnyCollectionDef, FieldsMap } from "@gettersethya/mira-collection";
|
|
2
|
+
import type { BrowserAuth, ServerAuth } from "./auth.js";
|
|
3
|
+
import type { CollectionClient, RetryOptions } from "./collection.js";
|
|
4
|
+
import type { ClientHandler } from "./handler.js";
|
|
5
|
+
import type { InferRecord } from "./types.js";
|
|
6
|
+
type CollectionAdapter = <F extends FieldsMap>(client: CollectionClient<F>, name: string) => CollectionClient<F>;
|
|
7
|
+
type BaseClient<A extends BrowserAuth | ServerAuth = BrowserAuth | ServerAuth> = {
|
|
8
|
+
collection<C extends AnyCollectionDef>(def: C): CollectionClient<C["fields"]>;
|
|
9
|
+
auth: A;
|
|
10
|
+
withCollections<M extends Record<string, AnyCollectionDef>>(map: M, opts?: {
|
|
11
|
+
adapter?: CollectionAdapter;
|
|
12
|
+
}): BaseClient<A> & CollectionAccessors<M>;
|
|
13
|
+
};
|
|
14
|
+
type CollectionAccessors<M extends Record<string, AnyCollectionDef>> = {
|
|
15
|
+
[K in keyof M]: CollectionClient<M[K]["fields"]> & (M[K]["schema"]["x-collection-kind"] extends "auth" ? {
|
|
16
|
+
authWithPassword(): ClientHandler<{
|
|
17
|
+
token: string;
|
|
18
|
+
record: InferRecord<M[K]["fields"]>;
|
|
19
|
+
}, {
|
|
20
|
+
email: string;
|
|
21
|
+
password: string;
|
|
22
|
+
}>;
|
|
23
|
+
} : {});
|
|
24
|
+
};
|
|
25
|
+
type BrowserMiraClient = BaseClient<BrowserAuth>;
|
|
26
|
+
type ServerMiraClient = BaseClient<ServerAuth>;
|
|
27
|
+
/**
|
|
28
|
+
* Create a Mira client instance for the browser (default mode).
|
|
29
|
+
* Uses cookies for auth — the client tracks login state via `auth.isLoggedIn()`.
|
|
30
|
+
*
|
|
31
|
+
* @param baseUrl - Base URL of the Mira server (default: "/" for same-origin)
|
|
32
|
+
* @param opts.defaultRetryOptions - Optional default retry schedule for all operations
|
|
33
|
+
* @returns A BrowserMiraClient with `auth: BrowserAuth`
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* import { createMiraClient } from "@gettersethya/mira-client"
|
|
37
|
+
*
|
|
38
|
+
* const mira = createMiraClient("http://localhost:3000")
|
|
39
|
+
* const posts = await mira.posts.getList().raw()
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // With retry options
|
|
43
|
+
* import { Schedule } from "effect"
|
|
44
|
+
* const mira = createMiraClient("/", {
|
|
45
|
+
* defaultRetryOptions: { schedule: Schedule.exponential(100) }
|
|
46
|
+
* })
|
|
47
|
+
*/
|
|
48
|
+
export declare function createMiraClient(baseUrl?: string, opts?: {
|
|
49
|
+
type?: "browser";
|
|
50
|
+
defaultRetryOptions?: RetryOptions;
|
|
51
|
+
}): BrowserMiraClient;
|
|
52
|
+
/**
|
|
53
|
+
* Create a Mira client instance for server-side rendering (SSR).
|
|
54
|
+
* Uses `type: "server"` to enable manual JWT token management via `auth: ServerAuth`.
|
|
55
|
+
*
|
|
56
|
+
* In server mode, the client does NOT track login state — you must call
|
|
57
|
+
* `mira.auth.setToken(token)` explicitly with the JWT from your SSR context.
|
|
58
|
+
*
|
|
59
|
+
* @param baseUrl - Base URL of the Mira server
|
|
60
|
+
* @param opts.type - Must be "server"
|
|
61
|
+
* @param opts.defaultRetryOptions - Optional default retry schedule
|
|
62
|
+
* @returns A ServerMiraClient with `auth: ServerAuth`
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* import { createMiraClient } from "@gettersethya/mira-client"
|
|
66
|
+
*
|
|
67
|
+
* const mira = createMiraClient("http://localhost:3000", { type: "server" })
|
|
68
|
+
* mira.auth.setToken("eyJ...") // set token from SSR context
|
|
69
|
+
* const posts = await mira.posts.getList().raw()
|
|
70
|
+
*/
|
|
71
|
+
export declare function createMiraClient(baseUrl: string | undefined, opts: {
|
|
72
|
+
type: "server";
|
|
73
|
+
defaultRetryOptions?: RetryOptions;
|
|
74
|
+
}): ServerMiraClient;
|
|
75
|
+
export {};
|
|
76
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/client/factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,cAAc,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,KAAK,iBAAiB,GAAG,CAAC,CAAC,SAAS,SAAS,EAC3C,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC3B,IAAI,EAAE,MAAM,KACT,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAExB,KAAK,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,IAAI;IAC/E,UAAU,CAAC,CAAC,SAAS,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7E,IAAI,EAAE,CAAC,CAAA;IACP,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACxD,GAAG,EAAE,CAAC,EACN,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAE,GACrC,UAAU,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAA;CAC1C,CAAA;AAED,KAAK,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,IAAI;KACpE,CAAC,IAAI,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAC9C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,mBAAmB,CAAC,SAAS,MAAM,GAC/C;QACE,gBAAgB,IAAI,aAAa,CAC/B;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;SAAE,EACtD;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CACpC,CAAA;KACF,GACD,EAAE,CAAC;CACV,CAAA;AAED,KAAK,iBAAiB,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;AAEhD,KAAK,gBAAgB,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;AAwG9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,mBAAmB,CAAC,EAAE,YAAY,CAAA;CAAE,GAC9D,iBAAiB,CAAA;AAEpB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,mBAAmB,CAAC,EAAE,YAAY,CAAA;CAAE,GAC3D,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { HttpClient, HttpClientRequest as HCR } from "@effect/platform";
|
|
2
|
+
import { Effect, MutableRef } from "effect";
|
|
3
|
+
import { makeBrowserAuth, makeServerAuth } from "./auth.js";
|
|
4
|
+
import { makeCollectionClient } from "./collection.js";
|
|
5
|
+
import { MiraError } from "./errors.js";
|
|
6
|
+
import { makeClientHandler as makeHandler } from "./handler.js";
|
|
7
|
+
function catchAllErrors(effect) {
|
|
8
|
+
return effect.pipe(Effect.catchTags({
|
|
9
|
+
RequestError: (e) => Effect.fail(new MiraError({ status: 0, body: e.message })),
|
|
10
|
+
ResponseError: (e) => Effect.fail(new MiraError({ status: e.response.status, body: e.message })),
|
|
11
|
+
HttpBodyError: (e) => Effect.fail(new MiraError({ status: 500, body: String(e) }))
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
function createExecute(baseUrl, authTokenRef) {
|
|
15
|
+
return (req) => {
|
|
16
|
+
const raw = Effect.gen(function* () {
|
|
17
|
+
const http = yield* HttpClient.HttpClient;
|
|
18
|
+
const token = authTokenRef ? MutableRef.get(authTokenRef) : null;
|
|
19
|
+
const finalReq = HCR.prependUrl(baseUrl)(token ? HCR.setHeader(req, "Authorization", `Bearer ${token}`) : req);
|
|
20
|
+
const res = yield* http.execute(finalReq);
|
|
21
|
+
if (res.status >= 400) {
|
|
22
|
+
const body = yield* res.json;
|
|
23
|
+
return yield* new MiraError({ status: res.status, body });
|
|
24
|
+
}
|
|
25
|
+
if (res.status === 204) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return (yield* res.json);
|
|
29
|
+
});
|
|
30
|
+
return catchAllErrors(raw);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createMiraClientInternal(baseUrl = "/", type = "browser", defaultRetryOptions) {
|
|
34
|
+
const fileTokenCacheRef = MutableRef.make(new Map());
|
|
35
|
+
const authTokenRef = type === "server" ? MutableRef.make(null) : null;
|
|
36
|
+
const loggedInRef = type === "browser" ? MutableRef.make(false) : null;
|
|
37
|
+
const execute = createExecute(baseUrl, authTokenRef);
|
|
38
|
+
const makeClientHandler = (effect) => makeHandler(effect);
|
|
39
|
+
function buildCollectionClient(def) {
|
|
40
|
+
const isAuth = def.schema["x-collection-kind"] === "auth";
|
|
41
|
+
return makeCollectionClient({
|
|
42
|
+
collectionName: def.name,
|
|
43
|
+
schema: def.schema,
|
|
44
|
+
fields: def.fields,
|
|
45
|
+
execute,
|
|
46
|
+
baseUrl,
|
|
47
|
+
authTokenRef,
|
|
48
|
+
loggedInRef,
|
|
49
|
+
fileTokenCacheRef,
|
|
50
|
+
isAuth,
|
|
51
|
+
...(defaultRetryOptions !== undefined ? { defaultRetryOptions } : {})
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function makeAuth() {
|
|
55
|
+
if (type === "server" && authTokenRef !== null) {
|
|
56
|
+
return makeServerAuth(authTokenRef, fileTokenCacheRef);
|
|
57
|
+
}
|
|
58
|
+
if (loggedInRef !== null) {
|
|
59
|
+
return makeBrowserAuth(execute, makeClientHandler, loggedInRef);
|
|
60
|
+
}
|
|
61
|
+
return makeBrowserAuth(execute, makeClientHandler, MutableRef.make(false));
|
|
62
|
+
}
|
|
63
|
+
function withCollections(map, opts) {
|
|
64
|
+
const baseClient = buildBaseClient();
|
|
65
|
+
const collections = {};
|
|
66
|
+
for (const key of Object.keys(map)) {
|
|
67
|
+
const raw = buildCollectionClient(map[key]);
|
|
68
|
+
collections[key] = (opts?.adapter ? opts.adapter(raw, String(key)) : raw);
|
|
69
|
+
}
|
|
70
|
+
return Object.assign(baseClient, collections);
|
|
71
|
+
}
|
|
72
|
+
function buildBaseClient() {
|
|
73
|
+
return {
|
|
74
|
+
collection: (def) => buildCollectionClient(def),
|
|
75
|
+
auth: makeAuth(),
|
|
76
|
+
withCollections
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return buildBaseClient();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create a Mira client instance.
|
|
83
|
+
*
|
|
84
|
+
* In browser mode (default), auth is cookie-based and `isLoggedIn()` reflects
|
|
85
|
+
* client-side login state. In server mode, you manage the JWT token explicitly
|
|
86
|
+
* via `auth.setToken()`.
|
|
87
|
+
*
|
|
88
|
+
* Use `withCollections()` to create typed accessors for each collection:
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const mira = createMiraClient("/").withCollections({ posts, users })
|
|
92
|
+
* const posts = await mira.posts.getList().raw()
|
|
93
|
+
* const loginResult = await mira.users.authWithPassword().raw({
|
|
94
|
+
* email: "admin@test.com",
|
|
95
|
+
* password: "admin1234"
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* @see BrowserAuth — client-side auth
|
|
99
|
+
* @see ServerAuth — server-side auth
|
|
100
|
+
* @see CollectionClient — the per-collection client interface
|
|
101
|
+
*/
|
|
102
|
+
export function createMiraClient(baseUrl = "/", opts = {}) {
|
|
103
|
+
const { type = "browser", defaultRetryOptions } = opts;
|
|
104
|
+
return createMiraClientInternal(baseUrl, type, defaultRetryOptions);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/client/factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { HttpClient } from "@effect/platform";
|
|
2
|
+
import { Effect, MutableRef } from "effect";
|
|
3
|
+
import type { AnyCollectionDef, FieldsMap } from "@gettersethya/mira-collection";
|
|
4
|
+
import { MiraError } from "./errors.js";
|
|
5
|
+
import type { ClientHandler, ExecuteFn } from "./handler.js";
|
|
6
|
+
import type { CollectionFileFields } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Build a file request URL for the Mira file-serving endpoint.
|
|
9
|
+
*
|
|
10
|
+
* Constructs a URL of the form:
|
|
11
|
+
* `{baseUrl}/api/files/{collection}/{id}/{filename}?token={token}&thumb={spec}`
|
|
12
|
+
*
|
|
13
|
+
* Query parameters are only appended when defined.
|
|
14
|
+
*
|
|
15
|
+
* @param baseUrl - The base URL of the Mira server (e.g., "http://localhost:3000" or "/" for same-origin)
|
|
16
|
+
* @param collection - The collection name
|
|
17
|
+
* @param id - The record ID
|
|
18
|
+
* @param filename - The filename as stored in the record's file field
|
|
19
|
+
* @param opts.token - Optional short-lived JWT token for protected files
|
|
20
|
+
* @param opts.thumb - Optional thumbnail spec (e.g., "200x200", "100x100_fit")
|
|
21
|
+
* @returns The fully constructed file URL string
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* buildFileUrl("/", "posts", "abc123", "cover.jpg")
|
|
25
|
+
* // "/api/files/posts/abc123/cover.jpg"
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* buildFileUrl("http://localhost:8090", "users", "u1", "avatar.png", {
|
|
29
|
+
* token: "eyJ...",
|
|
30
|
+
* thumb: "200x200"
|
|
31
|
+
* })
|
|
32
|
+
* // "http://localhost:8090/api/files/users/u1/avatar.png?token=eyJ...&thumb=200x200"
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildFileUrl(baseUrl: string, collection: string, id: string, filename: string, opts?: {
|
|
35
|
+
token?: string;
|
|
36
|
+
thumb?: string;
|
|
37
|
+
}): string;
|
|
38
|
+
/**
|
|
39
|
+
* Create a function that retrieves a short-lived file-access JWT token for a collection.
|
|
40
|
+
* Tokens are cached per collection with a 30-second freshness buffer before expiry.
|
|
41
|
+
*
|
|
42
|
+
* @internal Called internally by `makeFileFields`. Use `ProtectedFileFieldClient.getToken()` instead.
|
|
43
|
+
*/
|
|
44
|
+
export declare function makeGetFileToken(execute: ExecuteFn, cacheRef: MutableRef.MutableRef<Map<string, {
|
|
45
|
+
token: string;
|
|
46
|
+
expiresAt: number;
|
|
47
|
+
}>>): (collection: string) => Effect.Effect<string, MiraError, HttpClient.HttpClient>;
|
|
48
|
+
/**
|
|
49
|
+
* Client interface for a public (non-protected) file field.
|
|
50
|
+
* File URLs are constructed synchronously because no auth token is needed.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Given a post with a public "cover" file field
|
|
54
|
+
* const url = post.fields.cover.url(post.id, "cover.jpg")
|
|
55
|
+
* // "/api/files/posts/abc/cover.jpg"
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // With thumbnail variant
|
|
59
|
+
* const thumbUrl = post.fields.cover.url(post.id, "cover.jpg", { thumb: "200x200" })
|
|
60
|
+
*
|
|
61
|
+
* @see ProtectedFileFieldClient — file client that requires auth tokens
|
|
62
|
+
* @see buildFileUrl — underlying URL builder
|
|
63
|
+
*/
|
|
64
|
+
export type PublicFileFieldClient = {
|
|
65
|
+
isProtected: false;
|
|
66
|
+
url(id: string, filename: string, opts?: {
|
|
67
|
+
thumb?: string;
|
|
68
|
+
}): string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Client interface for a protected file field.
|
|
72
|
+
* Protected files require a short-lived JWT token to access.
|
|
73
|
+
*
|
|
74
|
+
* Three modes:
|
|
75
|
+
* - `url(id, filename, { token })` — synchronous URL construction when you already
|
|
76
|
+
* have a token (e.g., from `getToken()`)
|
|
77
|
+
* - `asyncUrl(id, filename)` — returns a `ClientHandler<string>` that fetches a token
|
|
78
|
+
* and constructs the URL in one async call
|
|
79
|
+
* - `getToken()` — fetches a fresh file-access token (cached for 30s by collection)
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Async URL construction (fetches token automatically)
|
|
83
|
+
* const url = await post.fields.avatar.asyncUrl(post.id, "avatar.png").raw()
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Manual token management for batch operations
|
|
87
|
+
* const token = await post.fields.avatar.getToken().raw()
|
|
88
|
+
* const u1 = post.fields.avatar.url("id1", "img1.png", { token })
|
|
89
|
+
* const u2 = post.fields.avatar.url("id2", "img2.png", { token })
|
|
90
|
+
*
|
|
91
|
+
* @see PublicFileFieldClient — file client for unprotected files
|
|
92
|
+
* @see buildFileUrl — underlying URL builder
|
|
93
|
+
*/
|
|
94
|
+
export type ProtectedFileFieldClient = {
|
|
95
|
+
isProtected: true;
|
|
96
|
+
asyncUrl(id: string, filename: string, opts?: {
|
|
97
|
+
thumb?: string;
|
|
98
|
+
}): ClientHandler<string>;
|
|
99
|
+
url(id: string, filename: string, opts: {
|
|
100
|
+
token: string;
|
|
101
|
+
thumb?: string;
|
|
102
|
+
}): string;
|
|
103
|
+
getToken(): ClientHandler<string>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Build the file field client interfaces for a collection.
|
|
107
|
+
* Iterates over the schema's properties, creating `PublicFileFieldClient` or
|
|
108
|
+
* `ProtectedFileFieldClient` instances for each `file`-kind field.
|
|
109
|
+
*
|
|
110
|
+
* @internal Called by `makeCollectionClient` — use `collection.fields` instead.
|
|
111
|
+
*/
|
|
112
|
+
export declare function makeFileFields<F extends FieldsMap>(collection: AnyCollectionDef, schema: AnyCollectionDef["schema"], baseUrl: string, execute: ExecuteFn, cacheRef: MutableRef.MutableRef<Map<string, {
|
|
113
|
+
token: string;
|
|
114
|
+
expiresAt: number;
|
|
115
|
+
}>>, makeClientHandler: <T>(effect: Effect.Effect<T, MiraError, HttpClient.HttpClient>) => ClientHandler<T>): CollectionFileFields<F>;
|
|
116
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/client/file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAA;AAGrE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,MAAM,CAOR;AAcD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,GACjF,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,CAkBjF;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,KAAK,CAAA;IAClB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAA;CACrE,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACxF,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAA;IAClF,QAAQ,IAAI,aAAa,CAAC,MAAM,CAAC,CAAA;CAClC,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAChD,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,EAClF,iBAAiB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,GACrG,oBAAoB,CAAC,CAAC,CAAC,CAoCzB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { HttpClientRequest as HCR } from "@effect/platform";
|
|
2
|
+
import { Effect, MutableRef } from "effect";
|
|
3
|
+
import { MiraError } from "./errors.js";
|
|
4
|
+
/**
|
|
5
|
+
* Build a file request URL for the Mira file-serving endpoint.
|
|
6
|
+
*
|
|
7
|
+
* Constructs a URL of the form:
|
|
8
|
+
* `{baseUrl}/api/files/{collection}/{id}/{filename}?token={token}&thumb={spec}`
|
|
9
|
+
*
|
|
10
|
+
* Query parameters are only appended when defined.
|
|
11
|
+
*
|
|
12
|
+
* @param baseUrl - The base URL of the Mira server (e.g., "http://localhost:3000" or "/" for same-origin)
|
|
13
|
+
* @param collection - The collection name
|
|
14
|
+
* @param id - The record ID
|
|
15
|
+
* @param filename - The filename as stored in the record's file field
|
|
16
|
+
* @param opts.token - Optional short-lived JWT token for protected files
|
|
17
|
+
* @param opts.thumb - Optional thumbnail spec (e.g., "200x200", "100x100_fit")
|
|
18
|
+
* @returns The fully constructed file URL string
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* buildFileUrl("/", "posts", "abc123", "cover.jpg")
|
|
22
|
+
* // "/api/files/posts/abc123/cover.jpg"
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* buildFileUrl("http://localhost:8090", "users", "u1", "avatar.png", {
|
|
26
|
+
* token: "eyJ...",
|
|
27
|
+
* thumb: "200x200"
|
|
28
|
+
* })
|
|
29
|
+
* // "http://localhost:8090/api/files/users/u1/avatar.png?token=eyJ...&thumb=200x200"
|
|
30
|
+
*/
|
|
31
|
+
export function buildFileUrl(baseUrl, collection, id, filename, opts) {
|
|
32
|
+
const base = `${baseUrl}/api/files/${collection}/${id}/${filename}`;
|
|
33
|
+
const params = new URLSearchParams();
|
|
34
|
+
if (opts?.token !== undefined)
|
|
35
|
+
params.set("token", opts.token);
|
|
36
|
+
if (opts?.thumb !== undefined)
|
|
37
|
+
params.set("thumb", opts.thumb);
|
|
38
|
+
const qs = params.toString();
|
|
39
|
+
return qs ? `${base}?${qs}` : base;
|
|
40
|
+
}
|
|
41
|
+
function toExecuteEffect(reqEffect, execute) {
|
|
42
|
+
return reqEffect.pipe(Effect.flatMap((req) => execute(req)), Effect.catchTag("HttpBodyError", (e) => Effect.fail(new MiraError({ status: 500, body: String(e) }))));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a function that retrieves a short-lived file-access JWT token for a collection.
|
|
46
|
+
* Tokens are cached per collection with a 30-second freshness buffer before expiry.
|
|
47
|
+
*
|
|
48
|
+
* @internal Called internally by `makeFileFields`. Use `ProtectedFileFieldClient.getToken()` instead.
|
|
49
|
+
*/
|
|
50
|
+
export function makeGetFileToken(execute, cacheRef) {
|
|
51
|
+
return (collection) => Effect.gen(function* () {
|
|
52
|
+
const cache = MutableRef.get(cacheRef);
|
|
53
|
+
const cached = cache.get(collection);
|
|
54
|
+
if (cached !== undefined && Date.now() < cached.expiresAt - 30_000) {
|
|
55
|
+
return cached.token;
|
|
56
|
+
}
|
|
57
|
+
const data = yield* toExecuteEffect(HCR.bodyJson(HCR.post("/api/files/token"), { collection }), execute);
|
|
58
|
+
const newCache = new Map(cache).set(collection, data);
|
|
59
|
+
MutableRef.set(cacheRef, newCache);
|
|
60
|
+
return data.token;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build the file field client interfaces for a collection.
|
|
65
|
+
* Iterates over the schema's properties, creating `PublicFileFieldClient` or
|
|
66
|
+
* `ProtectedFileFieldClient` instances for each `file`-kind field.
|
|
67
|
+
*
|
|
68
|
+
* @internal Called by `makeCollectionClient` — use `collection.fields` instead.
|
|
69
|
+
*/
|
|
70
|
+
export function makeFileFields(collection, schema, baseUrl, execute, cacheRef, makeClientHandler) {
|
|
71
|
+
const result = {};
|
|
72
|
+
const getFileToken = makeGetFileToken(execute, cacheRef);
|
|
73
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
74
|
+
if (prop["x-kind"] !== "file")
|
|
75
|
+
continue;
|
|
76
|
+
const isProtected = prop["x-protected"] === true;
|
|
77
|
+
if (isProtected) {
|
|
78
|
+
const protectedField = {
|
|
79
|
+
isProtected: true,
|
|
80
|
+
asyncUrl: (id, filename, opts) => makeClientHandler(Effect.gen(function* () {
|
|
81
|
+
const token = yield* getFileToken(collection.name);
|
|
82
|
+
return buildFileUrl(baseUrl, collection.name, id, filename, { token, ...(opts?.thumb !== undefined ? { thumb: opts.thumb } : {}) });
|
|
83
|
+
})),
|
|
84
|
+
url: (id, filename, opts) => buildFileUrl(baseUrl, collection.name, id, filename, { token: opts.token, ...(opts.thumb !== undefined ? { thumb: opts.thumb } : {}) }),
|
|
85
|
+
getToken: () => makeClientHandler(getFileToken(collection.name)),
|
|
86
|
+
};
|
|
87
|
+
result[key] = protectedField;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const publicField = {
|
|
91
|
+
isProtected: false,
|
|
92
|
+
url: (id, filename, opts) => buildFileUrl(baseUrl, collection.name, id, filename, opts),
|
|
93
|
+
};
|
|
94
|
+
result[key] = publicField;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/client/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { HttpClient, HttpClientRequest } from "@effect/platform";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import type { MiraError } from "./errors.js";
|
|
4
|
+
/**
|
|
5
|
+
* A dual-interface handler for dealing with Mira server responses.
|
|
6
|
+
*
|
|
7
|
+
* When `TInput extends void` (query operations: getList, getOne, getFirstOrNone, getFullList):
|
|
8
|
+
* - `.raw()` — returns `Promise<TData>`, throws `MiraError` on failure
|
|
9
|
+
* - `.toEffect()` — returns `Effect.Effect<TData, MiraError, HttpClient.HttpClient>`
|
|
10
|
+
*
|
|
11
|
+
* When `TInput` is provided (mutation operations: create, update, delete):
|
|
12
|
+
* - `.raw(input: TInput)` — returns `Promise<TData>`, throws `MiraError` on failure
|
|
13
|
+
* - `.toEffect(input: TInput)` — returns `Effect.Effect<TData, MiraError, HttpClient.HttpClient>`
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* import type { ClientHandler } from "@gettersethya/mira-client"
|
|
17
|
+
*
|
|
18
|
+
* // Query handler: TInput = void
|
|
19
|
+
* const listHandler: ClientHandler<{ items: Post[]; nextCursor: number | null }>
|
|
20
|
+
* const items = await listHandler.raw() // Promise-based
|
|
21
|
+
* const effect = listHandler.toEffect() // Effect-based
|
|
22
|
+
*
|
|
23
|
+
* // Mutation handler: TInput = { title: string }
|
|
24
|
+
* const createHandler: ClientHandler<Post, { title: string }>
|
|
25
|
+
* const post = await createHandler.raw({ title: "hello" })
|
|
26
|
+
* const createEffect = createHandler.toEffect({ title: "hello" })
|
|
27
|
+
*
|
|
28
|
+
* @see makeClientHandler — constructs a ClientHandler from an Effect
|
|
29
|
+
* @see makeMutationHandler — constructs a ClientHandler for mutations
|
|
30
|
+
* @see MiraError — the error thrown by .raw()
|
|
31
|
+
*/
|
|
32
|
+
export type ClientHandler<TData, TInput = void> = TInput extends void ? {
|
|
33
|
+
raw(): Promise<TData>;
|
|
34
|
+
toEffect(): Effect.Effect<TData, MiraError, HttpClient.HttpClient>;
|
|
35
|
+
} : {
|
|
36
|
+
raw(input: TInput): Promise<TData>;
|
|
37
|
+
toEffect(input: TInput): Effect.Effect<TData, MiraError, HttpClient.HttpClient>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Construct a `ClientHandler<T>` (query variant, TInput = void) from an Effect.
|
|
41
|
+
*
|
|
42
|
+
* The Effect is provided `FetchHttpClient.layer` at runtime when `.raw()` is called.
|
|
43
|
+
* The `.toEffect()` method returns the Effect without providing the layer, allowing
|
|
44
|
+
* the caller to supply their own `HttpClient` implementation (e.g., for testing).
|
|
45
|
+
*
|
|
46
|
+
* @param effect - The Effect to wrap. Must produce `T` on success or `MiraError` on failure
|
|
47
|
+
* @returns A ClientHandler with zero-arg .raw() and .toEffect()
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* import { Effect } from "effect"
|
|
51
|
+
* import { makeClientHandler } from "@gettersethya/mira-client"
|
|
52
|
+
*
|
|
53
|
+
* const handler = makeClientHandler<{ name: string }>(
|
|
54
|
+
* Effect.succeed({ name: "test" })
|
|
55
|
+
* )
|
|
56
|
+
* const result = await handler.raw() // { name: "test" }
|
|
57
|
+
*/
|
|
58
|
+
export declare function makeClientHandler<T>(effect: Effect.Effect<T, MiraError, HttpClient.HttpClient>): ClientHandler<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Construct a `ClientHandler<TData, TInput>` (mutation variant) from a function
|
|
61
|
+
* that accepts input and returns an Effect.
|
|
62
|
+
*
|
|
63
|
+
* The input is provided at call time (`.raw(input)` or `.toEffect(input)`).
|
|
64
|
+
* The Effect is provided `FetchHttpClient.layer` at runtime when `.raw()` is called.
|
|
65
|
+
*
|
|
66
|
+
* @param fn - A function that takes `TInput` and returns an Effect producing `TData`
|
|
67
|
+
* @returns A ClientHandler with input-arg .raw() and .toEffect()
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* import { Effect } from "effect"
|
|
71
|
+
* import { makeMutationHandler } from "@gettersethya/mira-client"
|
|
72
|
+
*
|
|
73
|
+
* const handler = makeMutationHandler<{ id: string }, { name: string }>(
|
|
74
|
+
* (input) => Effect.succeed({ id: "1", ...input })
|
|
75
|
+
* )
|
|
76
|
+
* const result = await handler.raw({ name: "test" }) // { id: "1", name: "test" }
|
|
77
|
+
*/
|
|
78
|
+
export declare function makeMutationHandler<TData, TInput>(fn: (input: TInput) => Effect.Effect<TData, MiraError, HttpClient.HttpClient>): ClientHandler<TData, TInput>;
|
|
79
|
+
/**
|
|
80
|
+
* The core HTTP execution function used internally by all client handlers.
|
|
81
|
+
* Takes an `HttpClientRequest`, sends it to the server, and returns the
|
|
82
|
+
* deserialized response body.
|
|
83
|
+
*
|
|
84
|
+
* Handles authentication token injection, base URL prefixing, and error mapping
|
|
85
|
+
* (HTTP 4xx/5xx responses become `MiraError` in the Effect error channel).
|
|
86
|
+
*
|
|
87
|
+
* @typeParam T - The expected response body type
|
|
88
|
+
* @param req - The HTTP request to execute (constructed via `HttpClientRequest.*`)
|
|
89
|
+
* @returns Effect that resolves to the parsed response body, or fails with MiraError
|
|
90
|
+
*/
|
|
91
|
+
export type ExecuteFn = <T>(req: HttpClientRequest.HttpClientRequest) => Effect.Effect<T, MiraError, HttpClient.HttpClient>;
|
|
92
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/client/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAErE,OAAO,EAAS,MAAM,EAAgB,MAAM,QAAQ,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,MAAM,SAAS,IAAI,GACjE;IACE,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAA;IACrB,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA;CACnE,GACD;IACE,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA;CAChF,CAAA;AAEL;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,GACzD,aAAa,CAAC,CAAC,CAAC,CAWlB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAC/C,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,GAC5E,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAY9B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,EACxB,GAAG,EAAE,iBAAiB,CAAC,iBAAiB,KACrC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FetchHttpClient } from "@effect/platform";
|
|
2
|
+
import { Cause, Effect, Exit, Option } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* Construct a `ClientHandler<T>` (query variant, TInput = void) from an Effect.
|
|
5
|
+
*
|
|
6
|
+
* The Effect is provided `FetchHttpClient.layer` at runtime when `.raw()` is called.
|
|
7
|
+
* The `.toEffect()` method returns the Effect without providing the layer, allowing
|
|
8
|
+
* the caller to supply their own `HttpClient` implementation (e.g., for testing).
|
|
9
|
+
*
|
|
10
|
+
* @param effect - The Effect to wrap. Must produce `T` on success or `MiraError` on failure
|
|
11
|
+
* @returns A ClientHandler with zero-arg .raw() and .toEffect()
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import { Effect } from "effect"
|
|
15
|
+
* import { makeClientHandler } from "@gettersethya/mira-client"
|
|
16
|
+
*
|
|
17
|
+
* const handler = makeClientHandler<{ name: string }>(
|
|
18
|
+
* Effect.succeed({ name: "test" })
|
|
19
|
+
* )
|
|
20
|
+
* const result = await handler.raw() // { name: "test" }
|
|
21
|
+
*/
|
|
22
|
+
export function makeClientHandler(effect) {
|
|
23
|
+
return {
|
|
24
|
+
raw: () => Effect.runPromiseExit(effect.pipe(Effect.provide(FetchHttpClient.layer))).then((exit) => {
|
|
25
|
+
if (Exit.isSuccess(exit))
|
|
26
|
+
return exit.value;
|
|
27
|
+
return Promise.reject(Option.getOrElse(Cause.failureOption(exit.cause), () => Cause.squash(exit.cause)));
|
|
28
|
+
}),
|
|
29
|
+
toEffect: () => effect,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Construct a `ClientHandler<TData, TInput>` (mutation variant) from a function
|
|
34
|
+
* that accepts input and returns an Effect.
|
|
35
|
+
*
|
|
36
|
+
* The input is provided at call time (`.raw(input)` or `.toEffect(input)`).
|
|
37
|
+
* The Effect is provided `FetchHttpClient.layer` at runtime when `.raw()` is called.
|
|
38
|
+
*
|
|
39
|
+
* @param fn - A function that takes `TInput` and returns an Effect producing `TData`
|
|
40
|
+
* @returns A ClientHandler with input-arg .raw() and .toEffect()
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* import { Effect } from "effect"
|
|
44
|
+
* import { makeMutationHandler } from "@gettersethya/mira-client"
|
|
45
|
+
*
|
|
46
|
+
* const handler = makeMutationHandler<{ id: string }, { name: string }>(
|
|
47
|
+
* (input) => Effect.succeed({ id: "1", ...input })
|
|
48
|
+
* )
|
|
49
|
+
* const result = await handler.raw({ name: "test" }) // { id: "1", name: "test" }
|
|
50
|
+
*/
|
|
51
|
+
export function makeMutationHandler(fn) {
|
|
52
|
+
const handler = {
|
|
53
|
+
raw: (input) => Effect.runPromiseExit(fn(input).pipe(Effect.provide(FetchHttpClient.layer))).then((exit) => {
|
|
54
|
+
if (Exit.isSuccess(exit))
|
|
55
|
+
return exit.value;
|
|
56
|
+
return Promise.reject(Option.getOrElse(Cause.failureOption(exit.cause), () => Cause.squash(exit.cause)));
|
|
57
|
+
}),
|
|
58
|
+
toEffect: (input) => fn(input),
|
|
59
|
+
};
|
|
60
|
+
return handler;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/client/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAyCpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAA0D;IAE1D,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CACR,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACtF,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAA;YAC3C,OAAO,OAAO,CAAC,MAAM,CACnB,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAClF,CAAA;QACH,CAAC,CAAC;QACJ,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;KACvB,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CACjC,EAA6E;IAE7E,MAAM,OAAO,GAAG;QACd,GAAG,EAAE,CAAC,KAAa,EAAE,EAAE,CACrB,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACzF,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAA;YAC3C,OAAO,OAAO,CAAC,MAAM,CACnB,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAClF,CAAA;QACH,CAAC,CAAC;QACJ,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;KACvC,CAAA;IACD,OAAO,OAAuC,CAAA;AAChD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { createMiraClient } from "./factory.js";
|
|
2
|
+
export { makeClientHandler, makeMutationHandler } from "./handler.js";
|
|
3
|
+
export type { ClientHandler, ExecuteFn } from "./handler.js";
|
|
4
|
+
export { MiraError } from "./errors.js";
|
|
5
|
+
export type { InferRecord, InferCreateInput, InferMutationInput, WithExpand, CollectionFileFields, RelationKeys, FileKeys } from "./types.js";
|
|
6
|
+
export type { BrowserAuth, ServerAuth } from "./auth.js";
|
|
7
|
+
export type { PublicFileFieldClient, ProtectedFileFieldClient } from "./file.js";
|
|
8
|
+
export { buildFileUrl } from "./file.js";
|
|
9
|
+
export { makeCollectionClient } from "./collection.js";
|
|
10
|
+
export type { CollectionClient } from "./collection.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACrE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,UAAU,EAAE,oBAAoB,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC7I,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACxD,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createMiraClient } from "./factory.js";
|
|
2
|
+
export { makeClientHandler, makeMutationHandler } from "./handler.js";
|
|
3
|
+
export { MiraError } from "./errors.js";
|
|
4
|
+
export { buildFileUrl } from "./file.js";
|
|
5
|
+
export { makeCollectionClient } from "./collection.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA"}
|