frontend client for gemstone. decentralised workplace app

feat: constellation helpers

serenity d084d574 d1fda020

Changed files
+74
src
+4
src/lib/consts.ts
···
};
export const DEFAULT_STALE_TIME = 5 * 60 * 1000;
···
};
export const DEFAULT_STALE_TIME = 5 * 60 * 1000;
+
+
export const CONSTELLATION_URL = new URL(
+
"https://constellation.microcosm.blue/",
+
);
+18
src/lib/types/constellation.ts
···
···
+
import { didSchema, nsidSchema } from "@/lib/types/atproto";
+
import { z } from "zod";
+
+
export const constellationBacklinkSchema = z.object({
+
did: didSchema,
+
collection: nsidSchema,
+
rkey: z.string(),
+
});
+
export type ConstellationBacklink = z.infer<typeof constellationBacklinkSchema>;
+
+
export const constellationBacklinkResponseSchema = z.object({
+
total: z.number(),
+
records: z.array(constellationBacklinkSchema),
+
cursor: z.optional(z.string().nullish()),
+
});
+
export type ConstellationBacklinkResponse = z.infer<
+
typeof constellationBacklinkResponseSchema
+
>;
+52
src/lib/utils/constellation.ts
···
···
+
import { CONSTELLATION_URL } from "@/lib/consts";
+
import type {
+
ConstellationBacklinkResponse} from "@/lib/types/constellation";
+
import {
+
constellationBacklinkResponseSchema,
+
} from "@/lib/types/constellation";
+
import type { Result } from "@/lib/utils/result";
+
import type { ZodError } from "zod";
+
+
export const getConstellationBacklink = async ({
+
subject,
+
source,
+
}: {
+
subject: string;
+
source: {
+
nsid: string;
+
fieldName?: string;
+
};
+
}): Promise<
+
Result<
+
ConstellationBacklinkResponse,
+
ZodError | { message: string; fetchStatus: number }
+
>
+
> => {
+
const { nsid, fieldName } = source;
+
const sourceParam = fieldName ? `${nsid}:${fieldName}` : nsid;
+
const req = new Request(
+
`${CONSTELLATION_URL.origin}/xrpc/blue.microcosm.links.getBacklinks?subject=${encodeURIComponent(subject)}&source=${encodeURIComponent(sourceParam)}`,
+
);
+
const res = await fetch(req);
+
+
if (!res.ok)
+
return {
+
ok: false,
+
error: {
+
message: "Fetch request to Constellation did not return 200.",
+
fetchStatus: res.status,
+
},
+
};
+
+
const data: unknown = await res.json();
+
+
const {
+
success,
+
error,
+
data: constellationResponse,
+
} = constellationBacklinkResponseSchema.safeParse(data);
+
+
if (!success) {
+
return { ok: false, error };
+
} else return { ok: true, data: constellationResponse };
+
};