@sudobility/sider_client 0.0.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/dist/client.d.ts +17 -0
- package/dist/client.js +38 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.js +13 -0
- package/dist/core.d.ts +2 -0
- package/dist/core.js +2 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +30 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/package.json +43 -0
- package/src/client.ts +60 -0
- package/src/context.tsx +14 -0
- package/src/core.ts +12 -0
- package/src/hooks.ts +36 -0
- package/src/index.ts +14 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CaptureRequest, CaptureResponse, Site, SiteLookupResult, StatsResponse, ToolCatalog } from "@sudobility/sider_types";
|
|
2
|
+
export interface SiderClientConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
/** Supplies auth headers (dev uid now, Firebase bearer later). */
|
|
5
|
+
getAuthHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
6
|
+
}
|
|
7
|
+
export declare class SiderClient {
|
|
8
|
+
private readonly config;
|
|
9
|
+
constructor(config: SiderClientConfig);
|
|
10
|
+
private req;
|
|
11
|
+
lookup(origin: string): Promise<SiteLookupResult>;
|
|
12
|
+
getSite(id: string): Promise<Site>;
|
|
13
|
+
listSites(): Promise<Site[]>;
|
|
14
|
+
getStats(): Promise<StatsResponse>;
|
|
15
|
+
getTools(siteId: string, includeProvisional?: boolean): Promise<ToolCatalog>;
|
|
16
|
+
uploadCapture(body: CaptureRequest): Promise<CaptureResponse>;
|
|
17
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SiderClient — the typed transport over sider_api. Usable in any JS context
|
|
2
|
+
// (React or a service worker); the React hooks in ./hooks wrap it. It unwraps
|
|
3
|
+
// the ApiResponse envelope and throws on error.
|
|
4
|
+
export class SiderClient {
|
|
5
|
+
config;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
async req(path, init) {
|
|
10
|
+
const auth = (await this.config.getAuthHeaders?.()) ?? {};
|
|
11
|
+
const res = await fetch(`${this.config.baseUrl}${path}`, {
|
|
12
|
+
...init,
|
|
13
|
+
headers: { "content-type": "application/json", ...auth, ...(init?.headers ?? {}) },
|
|
14
|
+
});
|
|
15
|
+
const json = (await res.json());
|
|
16
|
+
if (!json.success)
|
|
17
|
+
throw new Error(json.error);
|
|
18
|
+
return json.data;
|
|
19
|
+
}
|
|
20
|
+
lookup(origin) {
|
|
21
|
+
return this.req(`/api/v1/sites/lookup?origin=${encodeURIComponent(origin)}`);
|
|
22
|
+
}
|
|
23
|
+
getSite(id) {
|
|
24
|
+
return this.req(`/api/v1/sites/${id}`);
|
|
25
|
+
}
|
|
26
|
+
listSites() {
|
|
27
|
+
return this.req(`/api/v1/sites`);
|
|
28
|
+
}
|
|
29
|
+
getStats() {
|
|
30
|
+
return this.req(`/api/v1/stats`);
|
|
31
|
+
}
|
|
32
|
+
getTools(siteId, includeProvisional = false) {
|
|
33
|
+
return this.req(`/api/v1/sites/${siteId}/tools${includeProvisional ? "?includeProvisional=1" : ""}`);
|
|
34
|
+
}
|
|
35
|
+
uploadCapture(body) {
|
|
36
|
+
return this.req(`/api/v1/capture`, { method: "POST", body: JSON.stringify(body) });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { SiderClient } from "./client";
|
|
3
|
+
export declare function SiderClientProvider({ client, children }: {
|
|
4
|
+
client: SiderClient;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
export declare function useSiderClient(): SiderClient;
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
import { SiderClient } from "./client";
|
|
4
|
+
const SiderClientContext = createContext(null);
|
|
5
|
+
export function SiderClientProvider({ client, children }) {
|
|
6
|
+
return _jsx(SiderClientContext.Provider, { value: client, children: children });
|
|
7
|
+
}
|
|
8
|
+
export function useSiderClient() {
|
|
9
|
+
const c = useContext(SiderClientContext);
|
|
10
|
+
if (!c)
|
|
11
|
+
throw new Error("useSiderClient must be used within a <SiderClientProvider>");
|
|
12
|
+
return c;
|
|
13
|
+
}
|
package/dist/core.d.ts
ADDED
package/dist/core.js
ADDED
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CaptureRequest } from "@sudobility/sider_types";
|
|
2
|
+
export declare function useSiteLookup(origin: string): import("@tanstack/react-query").UseQueryResult<NoInfer<import("@sudobility/sider_types").SiteLookupResult>, Error>;
|
|
3
|
+
export declare function useStats(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("@sudobility/sider_types").StatsResponse>, Error>;
|
|
4
|
+
export declare function useSites(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("@sudobility/sider_types").Site[]>, Error>;
|
|
5
|
+
export declare function useToolCatalog(siteId: string | undefined, includeProvisional?: boolean): import("@tanstack/react-query").UseQueryResult<NoInfer<import("@sudobility/sider_types").ToolCatalog>, Error>;
|
|
6
|
+
export declare function useCaptureUpload(): import("@tanstack/react-query").UseMutationResult<import("@sudobility/sider_types").CaptureResponse, Error, CaptureRequest, unknown>;
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
2
|
+
import { useSiderClient } from "./context";
|
|
3
|
+
export function useSiteLookup(origin) {
|
|
4
|
+
const client = useSiderClient();
|
|
5
|
+
return useQuery({
|
|
6
|
+
queryKey: ["sider", "lookup", origin],
|
|
7
|
+
queryFn: () => client.lookup(origin),
|
|
8
|
+
enabled: Boolean(origin),
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export function useStats() {
|
|
12
|
+
const client = useSiderClient();
|
|
13
|
+
return useQuery({ queryKey: ["sider", "stats"], queryFn: () => client.getStats() });
|
|
14
|
+
}
|
|
15
|
+
export function useSites() {
|
|
16
|
+
const client = useSiderClient();
|
|
17
|
+
return useQuery({ queryKey: ["sider", "sites"], queryFn: () => client.listSites() });
|
|
18
|
+
}
|
|
19
|
+
export function useToolCatalog(siteId, includeProvisional = false) {
|
|
20
|
+
const client = useSiderClient();
|
|
21
|
+
return useQuery({
|
|
22
|
+
queryKey: ["sider", "tools", siteId, includeProvisional],
|
|
23
|
+
queryFn: () => client.getTools(siteId, includeProvisional),
|
|
24
|
+
enabled: Boolean(siteId),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function useCaptureUpload() {
|
|
28
|
+
const client = useSiderClient();
|
|
29
|
+
return useMutation({ mutationFn: (v) => client.uploadCapture(v) });
|
|
30
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sudobility/sider_client",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Sider frontend network library — typed API client + React Query hooks.",
|
|
5
|
+
"license": "BUSL-1.1",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "restricted"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "src/index.ts",
|
|
11
|
+
"types": "src/index.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./src/index.ts",
|
|
15
|
+
"default": "./src/index.ts"
|
|
16
|
+
},
|
|
17
|
+
"./core": {
|
|
18
|
+
"types": "./src/core.ts",
|
|
19
|
+
"default": "./src/core.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src",
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@sudobility/sider_types": "^0.0.2"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@tanstack/react-query": "^5",
|
|
35
|
+
"react": "^18 || ^19"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@tanstack/react-query": "^5.62.7",
|
|
39
|
+
"@types/react": "^18.3.12",
|
|
40
|
+
"react": "^18.3.1",
|
|
41
|
+
"typescript": "^5.9.3"
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// SiderClient — the typed transport over sider_api. Usable in any JS context
|
|
2
|
+
// (React or a service worker); the React hooks in ./hooks wrap it. It unwraps
|
|
3
|
+
// the ApiResponse envelope and throws on error.
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
ApiResponse,
|
|
7
|
+
CaptureRequest,
|
|
8
|
+
CaptureResponse,
|
|
9
|
+
Site,
|
|
10
|
+
SiteLookupResult,
|
|
11
|
+
StatsResponse,
|
|
12
|
+
ToolCatalog,
|
|
13
|
+
} from "@sudobility/sider_types";
|
|
14
|
+
|
|
15
|
+
export interface SiderClientConfig {
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
/** Supplies auth headers (dev uid now, Firebase bearer later). */
|
|
18
|
+
getAuthHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class SiderClient {
|
|
22
|
+
constructor(private readonly config: SiderClientConfig) {}
|
|
23
|
+
|
|
24
|
+
private async req<T>(path: string, init?: RequestInit): Promise<T> {
|
|
25
|
+
const auth = (await this.config.getAuthHeaders?.()) ?? {};
|
|
26
|
+
const res = await fetch(`${this.config.baseUrl}${path}`, {
|
|
27
|
+
...init,
|
|
28
|
+
headers: { "content-type": "application/json", ...auth, ...(init?.headers ?? {}) },
|
|
29
|
+
});
|
|
30
|
+
const json = (await res.json()) as ApiResponse<T>;
|
|
31
|
+
if (!json.success) throw new Error(json.error);
|
|
32
|
+
return json.data;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
lookup(origin: string) {
|
|
36
|
+
return this.req<SiteLookupResult>(`/api/v1/sites/lookup?origin=${encodeURIComponent(origin)}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getSite(id: string) {
|
|
40
|
+
return this.req<Site>(`/api/v1/sites/${id}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
listSites() {
|
|
44
|
+
return this.req<Site[]>(`/api/v1/sites`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getStats() {
|
|
48
|
+
return this.req<StatsResponse>(`/api/v1/stats`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getTools(siteId: string, includeProvisional = false) {
|
|
52
|
+
return this.req<ToolCatalog>(
|
|
53
|
+
`/api/v1/sites/${siteId}/tools${includeProvisional ? "?includeProvisional=1" : ""}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
uploadCapture(body: CaptureRequest) {
|
|
58
|
+
return this.req<CaptureResponse>(`/api/v1/capture`, { method: "POST", body: JSON.stringify(body) });
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/context.tsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext, useContext, type ReactNode } from "react";
|
|
2
|
+
import { SiderClient } from "./client";
|
|
3
|
+
|
|
4
|
+
const SiderClientContext = createContext<SiderClient | null>(null);
|
|
5
|
+
|
|
6
|
+
export function SiderClientProvider({ client, children }: { client: SiderClient; children: ReactNode }) {
|
|
7
|
+
return <SiderClientContext.Provider value={client}>{children}</SiderClientContext.Provider>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function useSiderClient(): SiderClient {
|
|
11
|
+
const c = useContext(SiderClientContext);
|
|
12
|
+
if (!c) throw new Error("useSiderClient must be used within a <SiderClientProvider>");
|
|
13
|
+
return c;
|
|
14
|
+
}
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// React-free entry point (for service workers / non-React contexts).
|
|
2
|
+
export * from "./client";
|
|
3
|
+
export type {
|
|
4
|
+
CaptureRequest,
|
|
5
|
+
CaptureResponse,
|
|
6
|
+
PlannerStep,
|
|
7
|
+
PlanStartResponse,
|
|
8
|
+
PlanStepResponse,
|
|
9
|
+
SiteLookupResult,
|
|
10
|
+
StatsResponse,
|
|
11
|
+
ToolCatalog,
|
|
12
|
+
} from "@sudobility/sider_types";
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
2
|
+
import type { CaptureRequest } from "@sudobility/sider_types";
|
|
3
|
+
import { useSiderClient } from "./context";
|
|
4
|
+
|
|
5
|
+
export function useSiteLookup(origin: string) {
|
|
6
|
+
const client = useSiderClient();
|
|
7
|
+
return useQuery({
|
|
8
|
+
queryKey: ["sider", "lookup", origin],
|
|
9
|
+
queryFn: () => client.lookup(origin),
|
|
10
|
+
enabled: Boolean(origin),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function useStats() {
|
|
15
|
+
const client = useSiderClient();
|
|
16
|
+
return useQuery({ queryKey: ["sider", "stats"], queryFn: () => client.getStats() });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useSites() {
|
|
20
|
+
const client = useSiderClient();
|
|
21
|
+
return useQuery({ queryKey: ["sider", "sites"], queryFn: () => client.listSites() });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useToolCatalog(siteId: string | undefined, includeProvisional = false) {
|
|
25
|
+
const client = useSiderClient();
|
|
26
|
+
return useQuery({
|
|
27
|
+
queryKey: ["sider", "tools", siteId, includeProvisional],
|
|
28
|
+
queryFn: () => client.getTools(siteId as string, includeProvisional),
|
|
29
|
+
enabled: Boolean(siteId),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useCaptureUpload() {
|
|
34
|
+
const client = useSiderClient();
|
|
35
|
+
return useMutation({ mutationFn: (v: CaptureRequest) => client.uploadCapture(v) });
|
|
36
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @sudobility/sider_client — typed API client + React Query hooks for sider_api.
|
|
2
|
+
export * from "./client";
|
|
3
|
+
export * from "./context";
|
|
4
|
+
export * from "./hooks";
|
|
5
|
+
export type {
|
|
6
|
+
CaptureRequest,
|
|
7
|
+
CaptureResponse,
|
|
8
|
+
PlannerStep,
|
|
9
|
+
PlanStartResponse,
|
|
10
|
+
PlanStepResponse,
|
|
11
|
+
SiteLookupResult,
|
|
12
|
+
StatsResponse,
|
|
13
|
+
ToolCatalog,
|
|
14
|
+
} from "@sudobility/sider_types";
|