Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 1x 4x 4x 4x 4x 1x 1x 1x 1x 1x 4x 3x 4x 1x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 1x 2x 2x 2x 2x 1x 1x 2x | import { RestError } from "@azure/data-tables";
import type { ProfileEntity, ProfilePutBody } from "../models/user";
import { PROFILE_TEXT_MAX } from "../models/user";
import {
decodeJsonProperty,
encodeJsonProperty,
ensureTable,
nowIso,
} from "./tablesService";
/**
* Profiles table CRUD (data-model.md): PK = Google sub, RK = "profile", one
* row per user. Normalization mirrors the extension's setProfile exactly so
* the swap is behavior-preserving.
*/
const TABLE = "Profiles";
const ROW_KEY = "profile";
export interface StoredProfile {
text: string;
dealbreakers: string[];
updatedAt: string;
}
function isNotFound(err: unknown): boolean {
return err instanceof RestError && err.statusCode === 404;
}
export async function getProfile(sub: string): Promise<StoredProfile | null> {
const client = await ensureTable(TABLE);
try {
const entity = await client.getEntity<ProfileEntity>(sub, ROW_KEY);
return {
text: entity.text,
dealbreakers: decodeJsonProperty<string[]>(entity.dealbreakers, []),
updatedAt: entity.updatedAt,
};
} catch (err) {
if (isNotFound(err)) return null;
throw err;
}
}
export async function putProfile(
sub: string,
input: ProfilePutBody
): Promise<StoredProfile> {
const profile: StoredProfile = {
text: input.text.slice(0, PROFILE_TEXT_MAX),
dealbreakers: input.dealbreakers.map((d) => d.trim()).filter(Boolean),
updatedAt: nowIso(),
};
const client = await ensureTable(TABLE);
await client.upsertEntity(
{
partitionKey: sub,
rowKey: ROW_KEY,
text: profile.text,
dealbreakers: encodeJsonProperty(profile.dealbreakers),
updatedAt: profile.updatedAt,
schemaVersion: 1,
},
"Replace"
);
return profile;
}
export async function deleteProfile(sub: string): Promise<void> {
const client = await ensureTable(TABLE);
try {
await client.deleteEntity(sub, ROW_KEY);
} catch (err) {
if (isNotFound(err)) return;
throw err;
}
}
|