this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

overhaul power map object n stuff to make it better at handling errors n shit lmao

look at the code idfk

+175 -174
+1 -2
lexicons/dev/vielle/dnd/astral.json
··· 12 12 "properties": { 13 13 "points": { 14 14 "type": "integer", 15 - "minimum": 0, 16 - "default": 0 15 + "minimum": 0 17 16 }, 18 17 "powers": { 19 18 "type": "array",
+1 -2
src/lexicons/types/dev/vielle/dnd/astral.ts
··· 8 8 $type: /*#__PURE__*/ v.literal("dev.vielle.dnd.astral"), 9 9 /** 10 10 * @minimum 0 11 - * @default 0 12 11 */ 13 - points: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer(), 0), 12 + points: /*#__PURE__*/ v.integer(), 14 13 get powers() { 15 14 return /*#__PURE__*/ v.array(powerSchema); 16 15 },
+159 -169
src/lib/powers.ts
··· 1 1 import "@atcute/atproto"; 2 2 import { getAuth } from "./auth"; 3 - import { parentPowers, powerData, isPowerId } from "../consts/astral"; 3 + import { 4 + isPowerId, 5 + parentPowers, 6 + powerData, 7 + type powerId, 8 + } from "../consts/astral"; 4 9 import { DevVielleDndAstral } from "../lexicons"; 5 10 import { map } from "nanostores"; 6 - import { powerSchema } from "../lexicons/types/dev/vielle/dnd/astral"; 7 11 import type { ActorIdentifier } from "@atcute/lexicons"; 8 12 import { Client, simpleFetchHandler } from "@atcute/client"; 13 + import type { XRPCQueries, XRPCProcedures } from "@atcute/lexicons/ambient"; 9 14 import { 10 15 CompositeDidDocumentResolver, 11 16 CompositeHandleResolver, ··· 16 21 WellKnownHandleResolver, 17 22 } from "@atcute/identity-resolver"; 18 23 19 - const [client, _, did] = await getAuth(true); 20 - 21 - const res = await client 22 - .get("com.atproto.repo.getRecord", { 23 - params: { 24 - repo: did, 25 - collection: "dev.vielle.dnd.astral", 26 - rkey: "self", 27 - }, 28 - }) 29 - .then((res) => 30 - res.ok 31 - ? res.data.value 32 - : (() => { 33 - throw res.data; 34 - })(), 35 - ) 36 - .then( 37 - async (res) => 38 - await DevVielleDndAstral.mainSchema["~standard"].validate(res), 39 - ) 40 - .then((res) => 41 - !res.issues 42 - ? res.value 43 - : (() => { 44 - throw res.issues; 45 - })(), 46 - ) 47 - .catch((err) => { 48 - console.error(err); 49 - return null; 50 - }); 51 - 52 - if (!res) { 53 - await client 54 - .post("com.atproto.repo.createRecord", { 55 - input: { 56 - repo: did, 57 - collection: "dev.vielle.dnd.astral", 58 - rkey: "self", 59 - record: { 60 - $type: "dev.vielle.dnd.astral", 61 - points: 0, 62 - powers: [], 63 - }, 64 - }, 65 - }) 66 - .then((res) => 67 - res.ok 68 - ? window.location.assign(window.location.pathname) 69 - : console.warn(res.data), 70 - ) 71 - .catch((err) => console.warn(err)); 72 - throw "Failed to create record. Something seriously wrong here..."; 73 - } 74 - 75 - export const isValidPowers = (data: powerObj) => 24 + export const isValidPowers = (data: powerObject): boolean => 76 25 // all forceSelect are included in powers 77 26 Object.entries(powerData) 78 27 .filter(([_, { forceSelect }]) => forceSelect) ··· 99 48 // number of powers <= points 100 49 data.points >= data?.powers.length; 101 50 102 - export type powerObj = { 103 - points: number; 104 - powers: typeof res.powers; 51 + const auth = (() => { 52 + let client: Client<XRPCQueries, XRPCProcedures> | undefined, 53 + did: `did:${string}:${string}` | undefined; 54 + 55 + return async (): Promise< 56 + [Exclude<typeof client, undefined>, Exclude<typeof did, undefined>] 57 + > => { 58 + if (!(client && did)) { 59 + const [n_client, _, n_did] = await getAuth(true); 60 + [client, did] = [n_client, n_did]; 61 + } 62 + return [client, did]; 63 + }; 64 + })(); 65 + 66 + type Prettify<T> = { 67 + [K in keyof T]: T[K]; 68 + } & {}; 69 + 70 + export type powerObject = Prettify<Omit<DevVielleDndAstral.Main, "$type">>; 71 + 72 + const requiredPowers = Object.entries(powerData) 73 + .filter(([id, { forceSelect }]) => isPowerId(id) && forceSelect) 74 + .map(([id]) => id as powerId); 75 + const initial: powerObject = { 76 + points: requiredPowers.length, 77 + powers: [...requiredPowers], 105 78 }; 106 79 107 - const powers = map<powerObj>({ 108 - points: res.points, 109 - powers: [...res.powers], 80 + const powers = map<powerObject>({ 81 + points: initial.points, 82 + powers: [...initial.powers], 110 83 }); 111 84 112 - export default { 113 - ...powers, 114 - async set(next: powerObj): Promise<powerObj> { 115 - if (!isValidPowers(next)) throw new TypeError("Not a valid powerset"); 116 - 117 - const { ok, data } = await client.post("com.atproto.repo.putRecord", { 118 - input: { 119 - repo: did, 120 - collection: "dev.vielle.dnd.astral", 121 - rkey: "self", 122 - record: { 123 - $type: "dev.vielle.dnd.astral", 124 - ...next, 125 - }, 85 + async function set(next: powerObject) { 86 + if (!isValidPowers(next)) { 87 + const repair = confirm( 88 + "Your powerlist is not valid. Would you like to repair it? This will reset your powers.", 89 + ); 90 + if (!repair) throw new TypeError("Invalid power layout."); 91 + else { 92 + set({ points: initial.points, powers: [...initial.powers] }); 93 + } 94 + } 95 + const [client, did] = await auth(); 96 + const { ok, data } = await client.post("com.atproto.repo.putRecord", { 97 + input: { 98 + repo: did, 99 + collection: "dev.vielle.dnd.astral", 100 + rkey: "self", 101 + record: { 102 + $type: "dev.vielle.dnd.astral", 103 + ...next, 126 104 }, 127 - }); 105 + }, 106 + }); 107 + if (!ok) { 108 + console.error(data); 109 + throw data; 110 + } 111 + powers.set(next); 112 + } 128 113 129 - if (!ok) { 130 - console.error(data); 131 - throw data; 132 - } 114 + // set a specific key; same as just calling set 115 + function setKey(key: "points", next: powerObject["points"]): Promise<void>; 116 + function setKey(key: "powers", next: powerObject["powers"]): Promise<void>; 117 + function setKey( 118 + key: "points" | "powers", 119 + next: powerObject["points" | "powers"], 120 + ): Promise<void> { 121 + // just pass call into set; it handles validation and auth 122 + return set({ 123 + ...powers.get(), 124 + [key]: next, 125 + }); 126 + } 133 127 134 - powers.set(next); 135 - return next; 136 - }, 128 + async function loadSelf() { 129 + const [client, did] = await auth(); 130 + const { ok, data } = await client.get("com.atproto.repo.getRecord", { 131 + params: { 132 + repo: did, 133 + collection: "dev.vielle.dnd.astral", 134 + rkey: "self", 135 + }, 136 + }); 137 + 138 + console.log(data); 137 139 138 - async setKey<T extends keyof powerObj>( 139 - key: T, 140 - value: powerObj[T], 141 - ): Promise<powerObj> { 142 - if (!isValidPowers({ ...powers.get(), [key]: value })) 143 - throw new TypeError("Not a valid powerset"); 140 + if (ok) { 141 + const res = await DevVielleDndAstral.mainSchema["~standard"].validate( 142 + data.value, 143 + ); 144 + if (res.issues) throw TypeError("Data not valid"); 145 + 146 + console.log(res.value, isValidPowers(res.value)); 147 + if (!isValidPowers(res.value)) { 148 + const repair = confirm( 149 + "Your powerlist is not valid. Would you like to repair it? This will reset your powers.", 150 + ); 151 + if (!repair) throw new TypeError("Invalid power layout."); 152 + else { 153 + set({ points: initial.points, powers: [...initial.powers] }); 154 + } 155 + } else 156 + powers.set({ 157 + points: res.value.points, 158 + powers: [...res.value.powers], 159 + }); 144 160 145 - const { ok, data } = await client.post("com.atproto.repo.putRecord", { 161 + // getRecord errored, try create the record 162 + // this does not update the power list as it sets it to the current value (assumed default) 163 + } else { 164 + const { ok } = await client.post("com.atproto.repo.createRecord", { 146 165 input: { 147 166 repo: did, 148 167 collection: "dev.vielle.dnd.astral", 149 168 rkey: "self", 150 - record: { 151 - $type: "dev.vielle.dnd.astral", 152 - ...powers.get(), 153 - [key]: value, 154 - }, 169 + record: powers.get(), 155 170 }, 156 171 }); 172 + if (!ok) throw new Error("Could not load or create data"); 173 + } 174 + } 157 175 158 - if (!ok) { 159 - console.error(data); 160 - throw data; 161 - } 176 + async function loadUser(user: ActorIdentifier) { 177 + const client = new Client({ 178 + handler: simpleFetchHandler({ 179 + service: await new LocalActorResolver({ 180 + handleResolver: new CompositeHandleResolver({ 181 + methods: { 182 + http: new WellKnownHandleResolver(), 183 + dns: new DohJsonHandleResolver({ 184 + dohUrl: "https://mozilla.cloudflare-dns.com/dns-query", 185 + }), 186 + }, 187 + strategy: "race", 188 + }), 189 + didDocumentResolver: new CompositeDidDocumentResolver({ 190 + methods: { 191 + web: new WebDidDocumentResolver(), 192 + plc: new PlcDidDocumentResolver(), 193 + }, 194 + }), 195 + }) 196 + .resolve(user) 197 + .then((doc) => doc.pds), 198 + }), 199 + }); 162 200 163 - powers.set({ 164 - ...powers.get(), 165 - [key]: value, 166 - }); 167 - return { 168 - ...powers.get(), 169 - [key]: value, 170 - }; 171 - }, 201 + const { ok, data } = await client.get("com.atproto.repo.getRecord", { 202 + params: { 203 + repo: user, 204 + collection: "dev.vielle.dnd.astral", 205 + rkey: "self", 206 + }, 207 + }); 172 208 173 - async loadUser(user: ActorIdentifier) { 174 - const res = await new Client({ 175 - handler: simpleFetchHandler({ 176 - service: await new LocalActorResolver({ 177 - handleResolver: new CompositeHandleResolver({ 178 - methods: { 179 - http: new WellKnownHandleResolver(), 180 - dns: new DohJsonHandleResolver({ 181 - dohUrl: "https://mozilla.cloudflare-dns.com/dns-query", 182 - }), 183 - }, 184 - strategy: "race", 185 - }), 186 - didDocumentResolver: new CompositeDidDocumentResolver({ 187 - methods: { 188 - web: new WebDidDocumentResolver(), 189 - plc: new PlcDidDocumentResolver(), 190 - }, 191 - }), 192 - }) 193 - .resolve(user) 194 - .then((doc) => doc.pds), 195 - }), 196 - }) 197 - .get("com.atproto.repo.getRecord", { 198 - params: { 199 - repo: user, 200 - collection: "dev.vielle.dnd.astral", 201 - rkey: "self", 202 - }, 203 - }) 204 - .then((res) => 205 - res.ok 206 - ? res.data.value 207 - : (() => { 208 - throw res.data; 209 - })(), 210 - ) 211 - .then( 212 - async (res) => 213 - await DevVielleDndAstral.mainSchema["~standard"].validate(res), 214 - ) 215 - .then((res) => 216 - !res.issues 217 - ? res.value 218 - : (() => { 219 - throw res.issues; 220 - })(), 221 - ) 222 - .catch((err) => { 223 - console.error(err); 224 - return null; 225 - }); 209 + if (!ok) throw new Error("Record not found. User may not have astral powers"); 210 + const value = data.value; 211 + const res = await DevVielleDndAstral.mainSchema["~standard"].validate(value); 212 + if (res.issues) throw new TypeError("Record was not valid"); 213 + powers.set({ 214 + points: res.value.points, 215 + powers: [...res.value.powers], 216 + }); 217 + } 226 218 227 - if (!res) throw "Failed to load user"; 219 + const proxy = { ...powers, set, setKey, loadSelf, loadUser }; 228 220 229 - powers.set({ points: res.points, powers: res.powers }); 230 - }, 231 - }; 221 + export default proxy;
+5 -1
src/pages/astral/[user].astro
··· 76 76 if (!("actor" in window)) throw ""; 77 77 const actor = window.actor as ActorIdentifier; 78 78 79 - await powers.loadUser(actor); 79 + await powers.loadUser(actor).catch((err) => { 80 + console.error(err); 81 + alert(`Warning: Got error loading account: ${err}`); 82 + throw err; 83 + }); 80 84 </script> 81 85 82 86 <Points immutable />
+9
src/pages/astral/index.astro
··· 45 45 } 46 46 </style> 47 47 48 + <script> 49 + import Powers from "../../lib/powers"; 50 + await Powers.loadSelf().catch((err) => { 51 + console.error(err); 52 + alert(`Warning: Got error loading account: ${err}`); 53 + throw err; 54 + }); 55 + </script> 56 + 48 57 <Points /> 49 58 50 59 <Powers {...powerTree} i={0} siblings={1} />