@singi-labs/sifa-sdk 0.19.62 → 0.19.64
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/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/rpg/catalog-drift.js +59 -0
- package/dist/rpg/catalog-drift.js.map +1 -0
- package/dist/rpg/catalog.js +76 -32
- package/dist/rpg/catalog.js.map +1 -1
- package/dist/rpg/index.cjs +75 -32
- package/dist/rpg/index.cjs.map +1 -1
- package/dist/rpg/index.d.cts +6 -2
- package/dist/rpg/index.d.ts +6 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7197,7 +7197,7 @@ function describeSifaRecord(collection, value) {
|
|
|
7197
7197
|
}
|
|
7198
7198
|
|
|
7199
7199
|
// src/index.ts
|
|
7200
|
-
var SIFA_SDK_VERSION = "0.19.
|
|
7200
|
+
var SIFA_SDK_VERSION = "0.19.64";
|
|
7201
7201
|
|
|
7202
7202
|
exports.ACTIVITY_TIERS = ACTIVITY_TIERS;
|
|
7203
7203
|
exports.ACTIVITY_VERBS = ACTIVITY_VERBS;
|
package/dist/index.js
CHANGED
|
@@ -353,7 +353,7 @@ import {
|
|
|
353
353
|
roadmapIssueUrl
|
|
354
354
|
} from "./roadmap/index.js";
|
|
355
355
|
import { SIFA_REPO_GROUPS, describeSifaRecord, repoGroupForCollection } from "./repo/index.js";
|
|
356
|
-
var SIFA_SDK_VERSION = "0.19.
|
|
356
|
+
var SIFA_SDK_VERSION = "0.19.64";
|
|
357
357
|
export {
|
|
358
358
|
ACTIVITY_TIERS,
|
|
359
359
|
ACTIVITY_VERBS,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/rpg/catalog-drift.ts
|
|
2
|
+
var SIFA_RPG_PROVIDER_DID = "did:plc:2f2ahswozqy4v5lvu676375y";
|
|
3
|
+
var COMPARED_FIELDS = ["title", "kind", "category", "assetCid", "iconCid"];
|
|
4
|
+
function compareRpgCatalog(ours, theirs, expectedProvider = SIFA_RPG_PROVIDER_DID) {
|
|
5
|
+
const remote = new Map(theirs.items.map((i) => [i.item, i]));
|
|
6
|
+
const mismatches = [];
|
|
7
|
+
for (const item of ours) {
|
|
8
|
+
if (!item.enabled) continue;
|
|
9
|
+
const r = remote.get(item.id);
|
|
10
|
+
if (!r) {
|
|
11
|
+
mismatches.push({ item: item.id, field: "listed", ours: "yes", theirs: "missing" });
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
for (const field of COMPARED_FIELDS) {
|
|
15
|
+
if (item[field] !== r[field]) {
|
|
16
|
+
mismatches.push({
|
|
17
|
+
item: item.id,
|
|
18
|
+
field,
|
|
19
|
+
ours: item[field],
|
|
20
|
+
theirs: r[field] ?? "(absent)"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const ourIds = new Set(ours.map((i) => i.id));
|
|
26
|
+
const extra = theirs.items.map((i) => i.item).filter((id) => !ourIds.has(id));
|
|
27
|
+
const providerMismatch = theirs.provider === expectedProvider ? null : { expected: expectedProvider, actual: String(theirs.provider) };
|
|
28
|
+
return { ok: !providerMismatch && mismatches.length === 0, providerMismatch, mismatches, extra };
|
|
29
|
+
}
|
|
30
|
+
function renderRpgCatalogDriftMarkdown(result) {
|
|
31
|
+
const lines = ["## rpg.actor item catalog drift", ""];
|
|
32
|
+
if (result.ok) lines.push("No drift: every enabled Sifa item matches rpg.actor.", "");
|
|
33
|
+
if (result.providerMismatch) {
|
|
34
|
+
lines.push(
|
|
35
|
+
`**Provider mismatch:** expected \`${result.providerMismatch.expected}\`, got \`${result.providerMismatch.actual}\`.`,
|
|
36
|
+
""
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (result.mismatches.length > 0) {
|
|
40
|
+
lines.push("| Item | Field | Ours | rpg.actor |", "| --- | --- | --- | --- |");
|
|
41
|
+
for (const m of result.mismatches) {
|
|
42
|
+
lines.push(`| ${m.item} | ${m.field} | ${m.ours} | ${m.theirs} |`);
|
|
43
|
+
}
|
|
44
|
+
lines.push("");
|
|
45
|
+
}
|
|
46
|
+
if (result.extra.length > 0) {
|
|
47
|
+
lines.push(
|
|
48
|
+
`Notice: rpg.actor lists items not in our catalog: ${result.extra.map((id) => `\`${id}\``).join(", ")}.`,
|
|
49
|
+
""
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return lines.join("\n");
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
SIFA_RPG_PROVIDER_DID,
|
|
56
|
+
compareRpgCatalog,
|
|
57
|
+
renderRpgCatalogDriftMarkdown
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=catalog-drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/rpg/catalog-drift.ts"],"sourcesContent":["/**\n * Pure comparison between our rpg.actor item catalog (`RPG_ITEMS`) and the\n * catalog rpg.actor serves at `GET /api/creator/items`. Used by\n * scripts/check-rpg-catalog.mjs (weekly drift check). Internal: deliberately\n * not re-exported from the `/rpg` barrel.\n */\nimport type { RpgItem } from './catalog.js';\n\n/** The sifa.id DID that owns the Sifa items on rpg.actor. */\nexport const SIFA_RPG_PROVIDER_DID = 'did:plc:2f2ahswozqy4v5lvu676375y';\n\nexport interface RpgActorItem {\n item: string;\n title?: string;\n description?: string;\n kind?: string;\n category?: string;\n channels?: string[];\n assetCid?: string;\n iconCid?: string;\n}\n\nexport interface RpgActorCatalog {\n provider: string;\n count?: number;\n items: RpgActorItem[];\n}\n\n/**\n * Fields that must match. `description` is left out on purpose: it is flavor\n * text that may be reworded on either side without affecting gifts.\n */\nconst COMPARED_FIELDS = ['title', 'kind', 'category', 'assetCid', 'iconCid'] as const;\n\nexport interface RpgCatalogMismatch {\n item: string;\n field: (typeof COMPARED_FIELDS)[number] | 'listed';\n ours: string;\n theirs: string;\n}\n\nexport interface RpgCatalogDriftResult {\n ok: boolean;\n providerMismatch: { expected: string; actual: string } | null;\n mismatches: RpgCatalogMismatch[];\n /** Items rpg.actor lists that we do not have. Informational only. */\n extra: string[];\n}\n\nexport function compareRpgCatalog(\n ours: readonly RpgItem[],\n theirs: RpgActorCatalog,\n expectedProvider: string = SIFA_RPG_PROVIDER_DID,\n): RpgCatalogDriftResult {\n const remote = new Map(theirs.items.map((i) => [i.item, i]));\n const mismatches: RpgCatalogMismatch[] = [];\n\n for (const item of ours) {\n if (!item.enabled) continue;\n const r = remote.get(item.id);\n if (!r) {\n mismatches.push({ item: item.id, field: 'listed', ours: 'yes', theirs: 'missing' });\n continue;\n }\n for (const field of COMPARED_FIELDS) {\n if (item[field] !== r[field]) {\n mismatches.push({\n item: item.id,\n field,\n ours: item[field],\n theirs: r[field] ?? '(absent)',\n });\n }\n }\n }\n\n const ourIds = new Set(ours.map((i) => i.id));\n const extra = theirs.items.map((i) => i.item).filter((id) => !ourIds.has(id));\n\n const providerMismatch =\n theirs.provider === expectedProvider\n ? null\n : { expected: expectedProvider, actual: String(theirs.provider) };\n\n return { ok: !providerMismatch && mismatches.length === 0, providerMismatch, mismatches, extra };\n}\n\nexport function renderRpgCatalogDriftMarkdown(result: RpgCatalogDriftResult): string {\n const lines = ['## rpg.actor item catalog drift', ''];\n if (result.ok) lines.push('No drift: every enabled Sifa item matches rpg.actor.', '');\n if (result.providerMismatch) {\n lines.push(\n `**Provider mismatch:** expected \\`${result.providerMismatch.expected}\\`, got \\`${result.providerMismatch.actual}\\`.`,\n '',\n );\n }\n if (result.mismatches.length > 0) {\n lines.push('| Item | Field | Ours | rpg.actor |', '| --- | --- | --- | --- |');\n for (const m of result.mismatches) {\n lines.push(`| ${m.item} | ${m.field} | ${m.ours} | ${m.theirs} |`);\n }\n lines.push('');\n }\n if (result.extra.length > 0) {\n lines.push(\n `Notice: rpg.actor lists items not in our catalog: ${result.extra.map((id) => `\\`${id}\\``).join(', ')}.`,\n '',\n );\n }\n return lines.join('\\n');\n}\n"],"mappings":";AASO,IAAM,wBAAwB;AAuBrC,IAAM,kBAAkB,CAAC,SAAS,QAAQ,YAAY,YAAY,SAAS;AAiBpE,SAAS,kBACd,MACA,QACA,mBAA2B,uBACJ;AACvB,QAAM,SAAS,IAAI,IAAI,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3D,QAAM,aAAmC,CAAC;AAE1C,aAAW,QAAQ,MAAM;AACvB,QAAI,CAAC,KAAK,QAAS;AACnB,UAAM,IAAI,OAAO,IAAI,KAAK,EAAE;AAC5B,QAAI,CAAC,GAAG;AACN,iBAAW,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,UAAU,MAAM,OAAO,QAAQ,UAAU,CAAC;AAClF;AAAA,IACF;AACA,eAAW,SAAS,iBAAiB;AACnC,UAAI,KAAK,KAAK,MAAM,EAAE,KAAK,GAAG;AAC5B,mBAAW,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,UACX;AAAA,UACA,MAAM,KAAK,KAAK;AAAA,UAChB,QAAQ,EAAE,KAAK,KAAK;AAAA,QACtB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5C,QAAM,QAAQ,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;AAE5E,QAAM,mBACJ,OAAO,aAAa,mBAChB,OACA,EAAE,UAAU,kBAAkB,QAAQ,OAAO,OAAO,QAAQ,EAAE;AAEpE,SAAO,EAAE,IAAI,CAAC,oBAAoB,WAAW,WAAW,GAAG,kBAAkB,YAAY,MAAM;AACjG;AAEO,SAAS,8BAA8B,QAAuC;AACnF,QAAM,QAAQ,CAAC,mCAAmC,EAAE;AACpD,MAAI,OAAO,GAAI,OAAM,KAAK,wDAAwD,EAAE;AACpF,MAAI,OAAO,kBAAkB;AAC3B,UAAM;AAAA,MACJ,qCAAqC,OAAO,iBAAiB,QAAQ,aAAa,OAAO,iBAAiB,MAAM;AAAA,MAChH;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,WAAW,SAAS,GAAG;AAChC,UAAM,KAAK,uCAAuC,2BAA2B;AAC7E,eAAW,KAAK,OAAO,YAAY;AACjC,YAAM,KAAK,KAAK,EAAE,IAAI,MAAM,EAAE,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,MAAM,IAAI;AAAA,IACnE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,UAAM;AAAA,MACJ,qDAAqD,OAAO,MAAM,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,MACrG;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
package/dist/rpg/catalog.js
CHANGED
|
@@ -14,86 +14,130 @@ var RpgUnlockSchema = z.discriminatedUnion("kind", [
|
|
|
14
14
|
z.object({ kind: z.literal("usesApp"), appId: z.string().min(1) }),
|
|
15
15
|
z.object({ kind: z.literal("hasDoctorate") })
|
|
16
16
|
]);
|
|
17
|
+
var RPG_CID_REGEX = /^bafkrei[a-z2-7]{52}$/;
|
|
17
18
|
var RpgItemSchema = z.object({
|
|
18
19
|
/** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */
|
|
19
20
|
id: z.string().min(1).max(50).regex(/^[a-z0-9_]+$/),
|
|
20
21
|
title: z.string().max(100),
|
|
21
22
|
description: z.string().max(500),
|
|
22
|
-
kind: z.enum(["layer", "held"]),
|
|
23
|
+
kind: z.enum(["layer", "held", "overlay"]),
|
|
23
24
|
category: z.string().max(30),
|
|
25
|
+
/** rpg.actor channels the item is offered in (optional). */
|
|
26
|
+
channels: z.array(z.string().min(1)).optional(),
|
|
27
|
+
/** Full-size sprite asset (CIDv1, raw codec, base32). */
|
|
28
|
+
assetCid: z.string().regex(RPG_CID_REGEX),
|
|
29
|
+
/** Inventory icon (CIDv1, raw codec, base32). */
|
|
30
|
+
iconCid: z.string().regex(RPG_CID_REGEX),
|
|
24
31
|
unlock: z.array(RpgUnlockSchema).min(1),
|
|
25
32
|
// ANY of these unlocks the item
|
|
26
33
|
enabled: z.boolean()
|
|
27
34
|
});
|
|
28
35
|
var RPG_ITEMS = [
|
|
29
36
|
{
|
|
30
|
-
id: "
|
|
31
|
-
title: "
|
|
32
|
-
description: "",
|
|
33
|
-
kind: "
|
|
34
|
-
category: "
|
|
37
|
+
id: "leather_briefcase",
|
|
38
|
+
title: "Leather Briefcase",
|
|
39
|
+
description: "A trusty briefcase, for your daily commute",
|
|
40
|
+
kind: "held",
|
|
41
|
+
category: "righthand",
|
|
42
|
+
channels: ["main"],
|
|
43
|
+
assetCid: "bafkreibjtgvetkpzwkliq4o4qnf7atbui6nxgyas3fyk6sjgd5zrl52swa",
|
|
44
|
+
iconCid: "bafkreifmyglopjtbkiuocmcjcbjhtr34vjumkzbnspbnlsezbdphbkfvu4",
|
|
35
45
|
enabled: true,
|
|
36
46
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.position" }]
|
|
37
47
|
},
|
|
38
48
|
{
|
|
39
|
-
id: "
|
|
40
|
-
title: "
|
|
41
|
-
description: "",
|
|
42
|
-
kind: "
|
|
43
|
-
category: "
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
id: "sifa_suit",
|
|
50
|
+
title: "Sifa Suit",
|
|
51
|
+
description: "Sharp power suit for confirmed professionals",
|
|
52
|
+
kind: "overlay",
|
|
53
|
+
category: "costume",
|
|
54
|
+
channels: ["main"],
|
|
55
|
+
assetCid: "bafkreibortlffvfzkdcuqdpoubczuno7ohnvfwqhefe4h4s36eooe4njgu",
|
|
56
|
+
iconCid: "bafkreifo7vojbr4i6uvsthj2hbczoqwmrn3ovysrskvxlxw6fvkbswm2ae",
|
|
57
|
+
enabled: false,
|
|
58
|
+
// Reserved for the confirmed tier (a colleague confirms the job and both
|
|
59
|
+
// have a confirmed work email). The unlock kind for that is added once work
|
|
60
|
+
// email confirmation exists; until then the item stays disabled.
|
|
61
|
+
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.position" }]
|
|
46
62
|
},
|
|
47
63
|
{
|
|
48
|
-
id: "
|
|
64
|
+
id: "speaker_mic",
|
|
49
65
|
title: "Speaker Mic",
|
|
50
|
-
description: "",
|
|
66
|
+
description: "A presentation mic, so you can drop it on 'em",
|
|
51
67
|
kind: "held",
|
|
52
68
|
category: "righthand",
|
|
69
|
+
channels: ["main"],
|
|
70
|
+
assetCid: "bafkreibr4kgeijc5naecf7l4awfv3omph4ngjmjb36qkfnk2sdo6l45ck4",
|
|
71
|
+
iconCid: "bafkreidnkirbw4nwiro3ocrn5nk66uxf3dhcoy5pojunisvs7so55u3j3q",
|
|
53
72
|
enabled: true,
|
|
54
73
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.presentation" }]
|
|
55
74
|
},
|
|
56
75
|
{
|
|
57
|
-
id: "
|
|
58
|
-
title: "
|
|
59
|
-
description: "",
|
|
76
|
+
id: "strapped_books",
|
|
77
|
+
title: "Strapped Books",
|
|
78
|
+
description: "Knowledge is power, better come strapped",
|
|
60
79
|
kind: "held",
|
|
61
|
-
category: "
|
|
80
|
+
category: "righthand",
|
|
81
|
+
channels: ["main"],
|
|
82
|
+
assetCid: "bafkreieofltl6427jy3n6dfv63phublalv6nq2hcs36qnyxz33ta6u6yqi",
|
|
83
|
+
iconCid: "bafkreiavywpv4sgw7gnkzq5gw3nq6yihaucdexpsvgko26q6jq6u6grjpi",
|
|
62
84
|
enabled: true,
|
|
63
85
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.education" }]
|
|
64
86
|
},
|
|
65
87
|
{
|
|
66
|
-
id: "
|
|
88
|
+
id: "dev_hoodie",
|
|
89
|
+
title: "Dev Hoodie",
|
|
90
|
+
description: "Snug hoodie for when you enter total code mode",
|
|
91
|
+
kind: "layer",
|
|
92
|
+
category: "tops",
|
|
93
|
+
channels: ["main", "sub1"],
|
|
94
|
+
assetCid: "bafkreigmrqp5kd6lytqcen2mypuv6dqonrdfbi2ngxhq3uqozk63yi7hoy",
|
|
95
|
+
iconCid: "bafkreigjwti3w43ta6gy2c75qtdnuvovfohjtv2febbd6hdhpri4tupbem",
|
|
96
|
+
enabled: true,
|
|
97
|
+
unlock: [
|
|
98
|
+
{ kind: "hasExternalAccount", platforms: ["github"] },
|
|
99
|
+
{ kind: "usesApp", appId: "tangled" }
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "doctoral_cap",
|
|
67
104
|
title: "Doctoral Cap",
|
|
68
|
-
description: "",
|
|
105
|
+
description: "Took so many long years to earn this hat",
|
|
69
106
|
kind: "layer",
|
|
70
107
|
category: "headwear",
|
|
108
|
+
channels: ["main"],
|
|
109
|
+
assetCid: "bafkreic7pvfpb7fjgooiaianrc27mh7fwj5vkicre63l6x5hrzb4w36tcq",
|
|
110
|
+
iconCid: "bafkreigqt6lmx5crj3w7vc3bvuewarzdreg2doxyeerbxmhljhpeshjewm",
|
|
71
111
|
enabled: true,
|
|
72
112
|
unlock: [{ kind: "hasDoctorate" }]
|
|
73
113
|
},
|
|
74
114
|
{
|
|
75
|
-
id: "
|
|
76
|
-
title: "
|
|
77
|
-
description: "",
|
|
115
|
+
id: "weekend_shirt",
|
|
116
|
+
title: "Weekend Shirt",
|
|
117
|
+
description: "Fun shirt to wear when work is all finished",
|
|
78
118
|
kind: "layer",
|
|
79
119
|
category: "tops",
|
|
120
|
+
channels: ["main", "sub1", "sub2"],
|
|
121
|
+
assetCid: "bafkreigifgpwkxvftiuzbjc6c2xz4xf2iv4bznbhu364e7rhvfmhosbak4",
|
|
122
|
+
iconCid: "bafkreieguco74wkabuyhs4sz6ec35nyywr7ikaw6et4coeezphnsnqqjui",
|
|
80
123
|
enabled: true,
|
|
81
|
-
unlock: [{ kind: "
|
|
124
|
+
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.volunteering" }]
|
|
82
125
|
},
|
|
83
126
|
{
|
|
84
|
-
id: "
|
|
85
|
-
title: "
|
|
86
|
-
description: "",
|
|
127
|
+
id: "lab_coat",
|
|
128
|
+
title: "Lab Coat",
|
|
129
|
+
description: "Scientifically proven attire",
|
|
87
130
|
kind: "layer",
|
|
88
131
|
category: "tops",
|
|
132
|
+
channels: ["main"],
|
|
133
|
+
assetCid: "bafkreiby4g6fgkmi65myv7tdblgb4jvqa3kgnrxvtkxlrtme55unuie4he",
|
|
134
|
+
iconCid: "bafkreifoddxk5tobgwadib5rxwjn67iind6me3swpvw4t5rbcauc5r4syy",
|
|
89
135
|
enabled: true,
|
|
90
|
-
unlock: [
|
|
91
|
-
{ kind: "hasExternalAccount", platforms: ["github"] },
|
|
92
|
-
{ kind: "usesApp", appId: "tangled" }
|
|
93
|
-
]
|
|
136
|
+
unlock: [{ kind: "hasExternalAccount", platforms: ["orcid"] }]
|
|
94
137
|
}
|
|
95
138
|
];
|
|
96
139
|
export {
|
|
140
|
+
RPG_CID_REGEX,
|
|
97
141
|
RPG_ITEMS,
|
|
98
142
|
RpgItemSchema,
|
|
99
143
|
RpgUnlockSchema
|
package/dist/rpg/catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rpg/catalog.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const RpgUnlockSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('hasRecord'),\n collection: z.enum([\n 'id.sifa.profile.position',\n 'id.sifa.profile.volunteering',\n 'id.sifa.profile.presentation',\n 'id.sifa.profile.education',\n ]),\n }),\n z.object({ kind: z.literal('hasExternalAccount'), platforms: z.array(z.string()).min(1) }),\n z.object({ kind: z.literal('usesApp'), appId: z.string().min(1) }),\n z.object({ kind: z.literal('hasDoctorate') }),\n]);\n\nexport const RpgItemSchema = z.object({\n /** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */\n id: z\n .string()\n .min(1)\n .max(50)\n .regex(/^[a-z0-9_]+$/),\n title: z.string().max(100),\n description: z.string().max(500),\n kind: z.enum(['layer', 'held']),\n category: z.string().max(30),\n unlock: z.array(RpgUnlockSchema).min(1), // ANY of these unlocks the item\n enabled: z.boolean(),\n});\nexport type RpgItem = z.infer<typeof RpgItemSchema>;\nexport type RpgUnlock = z.infer<typeof RpgUnlockSchema>;\n\n/**\n * The Sifa item catalog for rpg.actor.
|
|
1
|
+
{"version":3,"sources":["../../src/rpg/catalog.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const RpgUnlockSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('hasRecord'),\n collection: z.enum([\n 'id.sifa.profile.position',\n 'id.sifa.profile.volunteering',\n 'id.sifa.profile.presentation',\n 'id.sifa.profile.education',\n ]),\n }),\n z.object({ kind: z.literal('hasExternalAccount'), platforms: z.array(z.string()).min(1) }),\n z.object({ kind: z.literal('usesApp'), appId: z.string().min(1) }),\n z.object({ kind: z.literal('hasDoctorate') }),\n]);\n\n/** CIDv1 (raw codec, sha2-256, base32) as used for rpg.actor image blobs. */\nexport const RPG_CID_REGEX = /^bafkrei[a-z2-7]{52}$/;\n\nexport const RpgItemSchema = z.object({\n /** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */\n id: z\n .string()\n .min(1)\n .max(50)\n .regex(/^[a-z0-9_]+$/),\n title: z.string().max(100),\n description: z.string().max(500),\n kind: z.enum(['layer', 'held', 'overlay']),\n category: z.string().max(30),\n /** rpg.actor channels the item is offered in (optional). */\n channels: z.array(z.string().min(1)).optional(),\n /** Full-size sprite asset (CIDv1, raw codec, base32). */\n assetCid: z.string().regex(RPG_CID_REGEX),\n /** Inventory icon (CIDv1, raw codec, base32). */\n iconCid: z.string().regex(RPG_CID_REGEX),\n unlock: z.array(RpgUnlockSchema).min(1), // ANY of these unlocks the item\n enabled: z.boolean(),\n});\nexport type RpgItem = z.infer<typeof RpgItemSchema>;\nexport type RpgUnlock = z.infer<typeof RpgUnlockSchema>;\n\n/**\n * The Sifa item catalog for rpg.actor. Ids, titles, descriptions, kinds,\n * categories, channels and image CIDs come from rpg.actor's item cores.\n */\nexport const RPG_ITEMS: readonly RpgItem[] = [\n {\n id: 'leather_briefcase',\n title: 'Leather Briefcase',\n description: 'A trusty briefcase, for your daily commute',\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreibjtgvetkpzwkliq4o4qnf7atbui6nxgyas3fyk6sjgd5zrl52swa',\n iconCid: 'bafkreifmyglopjtbkiuocmcjcbjhtr34vjumkzbnspbnlsezbdphbkfvu4',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.position' }],\n },\n {\n id: 'sifa_suit',\n title: 'Sifa Suit',\n description: 'Sharp power suit for confirmed professionals',\n kind: 'overlay',\n category: 'costume',\n channels: ['main'],\n assetCid: 'bafkreibortlffvfzkdcuqdpoubczuno7ohnvfwqhefe4h4s36eooe4njgu',\n iconCid: 'bafkreifo7vojbr4i6uvsthj2hbczoqwmrn3ovysrskvxlxw6fvkbswm2ae',\n enabled: false,\n // Reserved for the confirmed tier (a colleague confirms the job and both\n // have a confirmed work email). The unlock kind for that is added once work\n // email confirmation exists; until then the item stays disabled.\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.position' }],\n },\n {\n id: 'speaker_mic',\n title: 'Speaker Mic',\n description: \"A presentation mic, so you can drop it on 'em\",\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreibr4kgeijc5naecf7l4awfv3omph4ngjmjb36qkfnk2sdo6l45ck4',\n iconCid: 'bafkreidnkirbw4nwiro3ocrn5nk66uxf3dhcoy5pojunisvs7so55u3j3q',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.presentation' }],\n },\n {\n id: 'strapped_books',\n title: 'Strapped Books',\n description: 'Knowledge is power, better come strapped',\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreieofltl6427jy3n6dfv63phublalv6nq2hcs36qnyxz33ta6u6yqi',\n iconCid: 'bafkreiavywpv4sgw7gnkzq5gw3nq6yihaucdexpsvgko26q6jq6u6grjpi',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.education' }],\n },\n {\n id: 'dev_hoodie',\n title: 'Dev Hoodie',\n description: 'Snug hoodie for when you enter total code mode',\n kind: 'layer',\n category: 'tops',\n channels: ['main', 'sub1'],\n assetCid: 'bafkreigmrqp5kd6lytqcen2mypuv6dqonrdfbi2ngxhq3uqozk63yi7hoy',\n iconCid: 'bafkreigjwti3w43ta6gy2c75qtdnuvovfohjtv2febbd6hdhpri4tupbem',\n enabled: true,\n unlock: [\n { kind: 'hasExternalAccount', platforms: ['github'] },\n { kind: 'usesApp', appId: 'tangled' },\n ],\n },\n {\n id: 'doctoral_cap',\n title: 'Doctoral Cap',\n description: 'Took so many long years to earn this hat',\n kind: 'layer',\n category: 'headwear',\n channels: ['main'],\n assetCid: 'bafkreic7pvfpb7fjgooiaianrc27mh7fwj5vkicre63l6x5hrzb4w36tcq',\n iconCid: 'bafkreigqt6lmx5crj3w7vc3bvuewarzdreg2doxyeerbxmhljhpeshjewm',\n enabled: true,\n unlock: [{ kind: 'hasDoctorate' }],\n },\n {\n id: 'weekend_shirt',\n title: 'Weekend Shirt',\n description: 'Fun shirt to wear when work is all finished',\n kind: 'layer',\n category: 'tops',\n channels: ['main', 'sub1', 'sub2'],\n assetCid: 'bafkreigifgpwkxvftiuzbjc6c2xz4xf2iv4bznbhu364e7rhvfmhosbak4',\n iconCid: 'bafkreieguco74wkabuyhs4sz6ec35nyywr7ikaw6et4coeezphnsnqqjui',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.volunteering' }],\n },\n {\n id: 'lab_coat',\n title: 'Lab Coat',\n description: 'Scientifically proven attire',\n kind: 'layer',\n category: 'tops',\n channels: ['main'],\n assetCid: 'bafkreiby4g6fgkmi65myv7tdblgb4jvqa3kgnrxvtkxlrtme55unuie4he',\n iconCid: 'bafkreifoddxk5tobgwadib5rxwjn67iind6me3swpvw4t5rbcauc5r4syy',\n enabled: true,\n unlock: [{ kind: 'hasExternalAccount', platforms: ['orcid'] }],\n },\n];\n"],"mappings":"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","names":[]}
|
package/dist/rpg/index.cjs
CHANGED
|
@@ -17,83 +17,126 @@ var RpgUnlockSchema = zod.z.discriminatedUnion("kind", [
|
|
|
17
17
|
zod.z.object({ kind: zod.z.literal("usesApp"), appId: zod.z.string().min(1) }),
|
|
18
18
|
zod.z.object({ kind: zod.z.literal("hasDoctorate") })
|
|
19
19
|
]);
|
|
20
|
+
var RPG_CID_REGEX = /^bafkrei[a-z2-7]{52}$/;
|
|
20
21
|
var RpgItemSchema = zod.z.object({
|
|
21
22
|
/** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */
|
|
22
23
|
id: zod.z.string().min(1).max(50).regex(/^[a-z0-9_]+$/),
|
|
23
24
|
title: zod.z.string().max(100),
|
|
24
25
|
description: zod.z.string().max(500),
|
|
25
|
-
kind: zod.z.enum(["layer", "held"]),
|
|
26
|
+
kind: zod.z.enum(["layer", "held", "overlay"]),
|
|
26
27
|
category: zod.z.string().max(30),
|
|
28
|
+
/** rpg.actor channels the item is offered in (optional). */
|
|
29
|
+
channels: zod.z.array(zod.z.string().min(1)).optional(),
|
|
30
|
+
/** Full-size sprite asset (CIDv1, raw codec, base32). */
|
|
31
|
+
assetCid: zod.z.string().regex(RPG_CID_REGEX),
|
|
32
|
+
/** Inventory icon (CIDv1, raw codec, base32). */
|
|
33
|
+
iconCid: zod.z.string().regex(RPG_CID_REGEX),
|
|
27
34
|
unlock: zod.z.array(RpgUnlockSchema).min(1),
|
|
28
35
|
// ANY of these unlocks the item
|
|
29
36
|
enabled: zod.z.boolean()
|
|
30
37
|
});
|
|
31
38
|
var RPG_ITEMS = [
|
|
32
39
|
{
|
|
33
|
-
id: "
|
|
34
|
-
title: "
|
|
35
|
-
description: "",
|
|
36
|
-
kind: "
|
|
37
|
-
category: "
|
|
40
|
+
id: "leather_briefcase",
|
|
41
|
+
title: "Leather Briefcase",
|
|
42
|
+
description: "A trusty briefcase, for your daily commute",
|
|
43
|
+
kind: "held",
|
|
44
|
+
category: "righthand",
|
|
45
|
+
channels: ["main"],
|
|
46
|
+
assetCid: "bafkreibjtgvetkpzwkliq4o4qnf7atbui6nxgyas3fyk6sjgd5zrl52swa",
|
|
47
|
+
iconCid: "bafkreifmyglopjtbkiuocmcjcbjhtr34vjumkzbnspbnlsezbdphbkfvu4",
|
|
38
48
|
enabled: true,
|
|
39
49
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.position" }]
|
|
40
50
|
},
|
|
41
51
|
{
|
|
42
|
-
id: "
|
|
43
|
-
title: "
|
|
44
|
-
description: "",
|
|
45
|
-
kind: "
|
|
46
|
-
category: "
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
id: "sifa_suit",
|
|
53
|
+
title: "Sifa Suit",
|
|
54
|
+
description: "Sharp power suit for confirmed professionals",
|
|
55
|
+
kind: "overlay",
|
|
56
|
+
category: "costume",
|
|
57
|
+
channels: ["main"],
|
|
58
|
+
assetCid: "bafkreibortlffvfzkdcuqdpoubczuno7ohnvfwqhefe4h4s36eooe4njgu",
|
|
59
|
+
iconCid: "bafkreifo7vojbr4i6uvsthj2hbczoqwmrn3ovysrskvxlxw6fvkbswm2ae",
|
|
60
|
+
enabled: false,
|
|
61
|
+
// Reserved for the confirmed tier (a colleague confirms the job and both
|
|
62
|
+
// have a confirmed work email). The unlock kind for that is added once work
|
|
63
|
+
// email confirmation exists; until then the item stays disabled.
|
|
64
|
+
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.position" }]
|
|
49
65
|
},
|
|
50
66
|
{
|
|
51
|
-
id: "
|
|
67
|
+
id: "speaker_mic",
|
|
52
68
|
title: "Speaker Mic",
|
|
53
|
-
description: "",
|
|
69
|
+
description: "A presentation mic, so you can drop it on 'em",
|
|
54
70
|
kind: "held",
|
|
55
71
|
category: "righthand",
|
|
72
|
+
channels: ["main"],
|
|
73
|
+
assetCid: "bafkreibr4kgeijc5naecf7l4awfv3omph4ngjmjb36qkfnk2sdo6l45ck4",
|
|
74
|
+
iconCid: "bafkreidnkirbw4nwiro3ocrn5nk66uxf3dhcoy5pojunisvs7so55u3j3q",
|
|
56
75
|
enabled: true,
|
|
57
76
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.presentation" }]
|
|
58
77
|
},
|
|
59
78
|
{
|
|
60
|
-
id: "
|
|
61
|
-
title: "
|
|
62
|
-
description: "",
|
|
79
|
+
id: "strapped_books",
|
|
80
|
+
title: "Strapped Books",
|
|
81
|
+
description: "Knowledge is power, better come strapped",
|
|
63
82
|
kind: "held",
|
|
64
|
-
category: "
|
|
83
|
+
category: "righthand",
|
|
84
|
+
channels: ["main"],
|
|
85
|
+
assetCid: "bafkreieofltl6427jy3n6dfv63phublalv6nq2hcs36qnyxz33ta6u6yqi",
|
|
86
|
+
iconCid: "bafkreiavywpv4sgw7gnkzq5gw3nq6yihaucdexpsvgko26q6jq6u6grjpi",
|
|
65
87
|
enabled: true,
|
|
66
88
|
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.education" }]
|
|
67
89
|
},
|
|
68
90
|
{
|
|
69
|
-
id: "
|
|
91
|
+
id: "dev_hoodie",
|
|
92
|
+
title: "Dev Hoodie",
|
|
93
|
+
description: "Snug hoodie for when you enter total code mode",
|
|
94
|
+
kind: "layer",
|
|
95
|
+
category: "tops",
|
|
96
|
+
channels: ["main", "sub1"],
|
|
97
|
+
assetCid: "bafkreigmrqp5kd6lytqcen2mypuv6dqonrdfbi2ngxhq3uqozk63yi7hoy",
|
|
98
|
+
iconCid: "bafkreigjwti3w43ta6gy2c75qtdnuvovfohjtv2febbd6hdhpri4tupbem",
|
|
99
|
+
enabled: true,
|
|
100
|
+
unlock: [
|
|
101
|
+
{ kind: "hasExternalAccount", platforms: ["github"] },
|
|
102
|
+
{ kind: "usesApp", appId: "tangled" }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "doctoral_cap",
|
|
70
107
|
title: "Doctoral Cap",
|
|
71
|
-
description: "",
|
|
108
|
+
description: "Took so many long years to earn this hat",
|
|
72
109
|
kind: "layer",
|
|
73
110
|
category: "headwear",
|
|
111
|
+
channels: ["main"],
|
|
112
|
+
assetCid: "bafkreic7pvfpb7fjgooiaianrc27mh7fwj5vkicre63l6x5hrzb4w36tcq",
|
|
113
|
+
iconCid: "bafkreigqt6lmx5crj3w7vc3bvuewarzdreg2doxyeerbxmhljhpeshjewm",
|
|
74
114
|
enabled: true,
|
|
75
115
|
unlock: [{ kind: "hasDoctorate" }]
|
|
76
116
|
},
|
|
77
117
|
{
|
|
78
|
-
id: "
|
|
79
|
-
title: "
|
|
80
|
-
description: "",
|
|
118
|
+
id: "weekend_shirt",
|
|
119
|
+
title: "Weekend Shirt",
|
|
120
|
+
description: "Fun shirt to wear when work is all finished",
|
|
81
121
|
kind: "layer",
|
|
82
122
|
category: "tops",
|
|
123
|
+
channels: ["main", "sub1", "sub2"],
|
|
124
|
+
assetCid: "bafkreigifgpwkxvftiuzbjc6c2xz4xf2iv4bznbhu364e7rhvfmhosbak4",
|
|
125
|
+
iconCid: "bafkreieguco74wkabuyhs4sz6ec35nyywr7ikaw6et4coeezphnsnqqjui",
|
|
83
126
|
enabled: true,
|
|
84
|
-
unlock: [{ kind: "
|
|
127
|
+
unlock: [{ kind: "hasRecord", collection: "id.sifa.profile.volunteering" }]
|
|
85
128
|
},
|
|
86
129
|
{
|
|
87
|
-
id: "
|
|
88
|
-
title: "
|
|
89
|
-
description: "",
|
|
130
|
+
id: "lab_coat",
|
|
131
|
+
title: "Lab Coat",
|
|
132
|
+
description: "Scientifically proven attire",
|
|
90
133
|
kind: "layer",
|
|
91
134
|
category: "tops",
|
|
135
|
+
channels: ["main"],
|
|
136
|
+
assetCid: "bafkreiby4g6fgkmi65myv7tdblgb4jvqa3kgnrxvtkxlrtme55unuie4he",
|
|
137
|
+
iconCid: "bafkreifoddxk5tobgwadib5rxwjn67iind6me3swpvw4t5rbcauc5r4syy",
|
|
92
138
|
enabled: true,
|
|
93
|
-
unlock: [
|
|
94
|
-
{ kind: "hasExternalAccount", platforms: ["github"] },
|
|
95
|
-
{ kind: "usesApp", appId: "tangled" }
|
|
96
|
-
]
|
|
139
|
+
unlock: [{ kind: "hasExternalAccount", platforms: ["orcid"] }]
|
|
97
140
|
}
|
|
98
141
|
];
|
|
99
142
|
|
package/dist/rpg/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rpg/catalog.ts","../../src/rpg/unlocks.ts","../../src/rpg/links.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\nexport const RpgUnlockSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('hasRecord'),\n collection: z.enum([\n 'id.sifa.profile.position',\n 'id.sifa.profile.volunteering',\n 'id.sifa.profile.presentation',\n 'id.sifa.profile.education',\n ]),\n }),\n z.object({ kind: z.literal('hasExternalAccount'), platforms: z.array(z.string()).min(1) }),\n z.object({ kind: z.literal('usesApp'), appId: z.string().min(1) }),\n z.object({ kind: z.literal('hasDoctorate') }),\n]);\n\nexport const RpgItemSchema = z.object({\n /** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */\n id: z\n .string()\n .min(1)\n .max(50)\n .regex(/^[a-z0-9_]+$/),\n title: z.string().max(100),\n description: z.string().max(500),\n kind: z.enum(['layer', 'held']),\n category: z.string().max(30),\n unlock: z.array(RpgUnlockSchema).min(1), // ANY of these unlocks the item\n enabled: z.boolean(),\n});\nexport type RpgItem = z.infer<typeof RpgItemSchema>;\nexport type RpgUnlock = z.infer<typeof RpgUnlockSchema>;\n\n/**\n * The Sifa item catalog for rpg.actor. PLACEHOLDER titles/categories until\n * rpg.actor transfers the real item cores.\n */\nexport const RPG_ITEMS: readonly RpgItem[] = [\n {\n id: 'sifa_power_suit',\n title: 'Power Suit',\n description: '',\n kind: 'layer',\n category: 'tops',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.position' }],\n },\n {\n id: 'sifa_weekend_shirt',\n title: 'Weekend Shirt',\n description: '',\n kind: 'layer',\n category: 'tops',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.volunteering' }],\n },\n {\n id: 'sifa_speaker_mic',\n title: 'Speaker Mic',\n description: '',\n kind: 'held',\n category: 'righthand',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.presentation' }],\n },\n {\n id: 'sifa_school_books',\n title: 'School Books',\n description: '',\n kind: 'held',\n category: 'lefthand',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.education' }],\n },\n {\n id: 'sifa_doctoral_cap',\n title: 'Doctoral Cap',\n description: '',\n kind: 'layer',\n category: 'headwear',\n enabled: true,\n unlock: [{ kind: 'hasDoctorate' }],\n },\n {\n id: 'sifa_lab_coat',\n title: 'Lab Coat',\n description: '',\n kind: 'layer',\n category: 'tops',\n enabled: true,\n unlock: [{ kind: 'hasExternalAccount', platforms: ['orcid'] }],\n },\n {\n id: 'sifa_dev_hoodie',\n title: 'Dev Hoodie',\n description: '',\n kind: 'layer',\n category: 'tops',\n enabled: true,\n unlock: [\n { kind: 'hasExternalAccount', platforms: ['github'] },\n { kind: 'usesApp', appId: 'tangled' },\n ],\n },\n];\n","import { RPG_ITEMS, type RpgItem, type RpgUnlock } from './catalog.js';\n\n/**\n * Profile signals the unlock rules are checked against. Callers must pass\n * lowercase platform codes (e.g. 'github', 'orcid') and registry app ids (e.g. 'tangled').\n */\nexport interface RpgUnlockSignals {\n collections: readonly string[];\n externalPlatforms: readonly string[];\n activeAppIds: readonly string[];\n hasDoctorate: boolean;\n}\n\n/** One enabled catalog item and whether the signals earn it. */\nexport interface RpgUnlockResult {\n item: RpgItem;\n earned: boolean;\n}\n\nfunction matches(u: RpgUnlock, s: RpgUnlockSignals): boolean {\n switch (u.kind) {\n case 'hasRecord':\n return s.collections.includes(u.collection);\n case 'hasExternalAccount':\n return u.platforms.some((p) => s.externalPlatforms.includes(p));\n case 'usesApp':\n return s.activeAppIds.includes(u.appId);\n case 'hasDoctorate':\n return s.hasDoctorate;\n }\n}\n\n/** Evaluate every enabled item (ANY matching unlock earns it); disabled items are omitted. */\nexport function evaluateRpgUnlocks(\n signals: RpgUnlockSignals,\n items: readonly RpgItem[] = RPG_ITEMS,\n): RpgUnlockResult[] {\n return items\n .filter((item) => item.enabled)\n .map((item) => ({ item, earned: item.unlock.some((u) => matches(u, signals)) }));\n}\n","/** Base URL of rpg.actor. */\nexport const RPG_ACTOR_URL = 'https://rpg.actor';\n\n/**\n * Record key of the `equipment.rpg.give` Sifa writes for an item. rpg.actor\n * stores the accepted `equipment.rpg.item` under the same key, so this also\n * identifies the item in the player's own account.\n *\n * The DID is used as-is: AT Protocol record keys allow `A-Za-z0-9 . - _ : ~`\n * (https://atproto.com/specs/record-key), so the colons in `did:plc:` are\n * valid. The format is already live in written gift records; do not change it.\n */\nexport function rpgGiveRkey(itemId: string, recipientDid: string): string {\n return `sifa-${itemId}-${recipientDid}`;\n}\n\n/** The player's character page on rpg.actor, where pending gifts can be accepted. */\nexport function rpgActorCharacterUrl(handleOrDid: string): string {\n return `${RPG_ACTOR_URL}/${encodeURIComponent(handleOrDid.replace(/^@+/, ''))}`;\n}\n\n/** Deep link that opens the Wear action for an accepted Sifa item on the character page. */\nexport function rpgActorWearUrl(handleOrDid: string, itemId: string, recipientDid: string): string {\n return `${rpgActorCharacterUrl(handleOrDid)}?wear=${encodeURIComponent(rpgGiveRkey(itemId, recipientDid))}`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/rpg/catalog.ts","../../src/rpg/unlocks.ts","../../src/rpg/links.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\nexport const RpgUnlockSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('hasRecord'),\n collection: z.enum([\n 'id.sifa.profile.position',\n 'id.sifa.profile.volunteering',\n 'id.sifa.profile.presentation',\n 'id.sifa.profile.education',\n ]),\n }),\n z.object({ kind: z.literal('hasExternalAccount'), platforms: z.array(z.string()).min(1) }),\n z.object({ kind: z.literal('usesApp'), appId: z.string().min(1) }),\n z.object({ kind: z.literal('hasDoctorate') }),\n]);\n\n/** CIDv1 (raw codec, sha2-256, base32) as used for rpg.actor image blobs. */\nexport const RPG_CID_REGEX = /^bafkrei[a-z2-7]{52}$/;\n\nexport const RpgItemSchema = z.object({\n /** Lowercase `[a-z0-9_]` only: the id is embedded in an AT Protocol record key. */\n id: z\n .string()\n .min(1)\n .max(50)\n .regex(/^[a-z0-9_]+$/),\n title: z.string().max(100),\n description: z.string().max(500),\n kind: z.enum(['layer', 'held', 'overlay']),\n category: z.string().max(30),\n /** rpg.actor channels the item is offered in (optional). */\n channels: z.array(z.string().min(1)).optional(),\n /** Full-size sprite asset (CIDv1, raw codec, base32). */\n assetCid: z.string().regex(RPG_CID_REGEX),\n /** Inventory icon (CIDv1, raw codec, base32). */\n iconCid: z.string().regex(RPG_CID_REGEX),\n unlock: z.array(RpgUnlockSchema).min(1), // ANY of these unlocks the item\n enabled: z.boolean(),\n});\nexport type RpgItem = z.infer<typeof RpgItemSchema>;\nexport type RpgUnlock = z.infer<typeof RpgUnlockSchema>;\n\n/**\n * The Sifa item catalog for rpg.actor. Ids, titles, descriptions, kinds,\n * categories, channels and image CIDs come from rpg.actor's item cores.\n */\nexport const RPG_ITEMS: readonly RpgItem[] = [\n {\n id: 'leather_briefcase',\n title: 'Leather Briefcase',\n description: 'A trusty briefcase, for your daily commute',\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreibjtgvetkpzwkliq4o4qnf7atbui6nxgyas3fyk6sjgd5zrl52swa',\n iconCid: 'bafkreifmyglopjtbkiuocmcjcbjhtr34vjumkzbnspbnlsezbdphbkfvu4',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.position' }],\n },\n {\n id: 'sifa_suit',\n title: 'Sifa Suit',\n description: 'Sharp power suit for confirmed professionals',\n kind: 'overlay',\n category: 'costume',\n channels: ['main'],\n assetCid: 'bafkreibortlffvfzkdcuqdpoubczuno7ohnvfwqhefe4h4s36eooe4njgu',\n iconCid: 'bafkreifo7vojbr4i6uvsthj2hbczoqwmrn3ovysrskvxlxw6fvkbswm2ae',\n enabled: false,\n // Reserved for the confirmed tier (a colleague confirms the job and both\n // have a confirmed work email). The unlock kind for that is added once work\n // email confirmation exists; until then the item stays disabled.\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.position' }],\n },\n {\n id: 'speaker_mic',\n title: 'Speaker Mic',\n description: \"A presentation mic, so you can drop it on 'em\",\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreibr4kgeijc5naecf7l4awfv3omph4ngjmjb36qkfnk2sdo6l45ck4',\n iconCid: 'bafkreidnkirbw4nwiro3ocrn5nk66uxf3dhcoy5pojunisvs7so55u3j3q',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.presentation' }],\n },\n {\n id: 'strapped_books',\n title: 'Strapped Books',\n description: 'Knowledge is power, better come strapped',\n kind: 'held',\n category: 'righthand',\n channels: ['main'],\n assetCid: 'bafkreieofltl6427jy3n6dfv63phublalv6nq2hcs36qnyxz33ta6u6yqi',\n iconCid: 'bafkreiavywpv4sgw7gnkzq5gw3nq6yihaucdexpsvgko26q6jq6u6grjpi',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.education' }],\n },\n {\n id: 'dev_hoodie',\n title: 'Dev Hoodie',\n description: 'Snug hoodie for when you enter total code mode',\n kind: 'layer',\n category: 'tops',\n channels: ['main', 'sub1'],\n assetCid: 'bafkreigmrqp5kd6lytqcen2mypuv6dqonrdfbi2ngxhq3uqozk63yi7hoy',\n iconCid: 'bafkreigjwti3w43ta6gy2c75qtdnuvovfohjtv2febbd6hdhpri4tupbem',\n enabled: true,\n unlock: [\n { kind: 'hasExternalAccount', platforms: ['github'] },\n { kind: 'usesApp', appId: 'tangled' },\n ],\n },\n {\n id: 'doctoral_cap',\n title: 'Doctoral Cap',\n description: 'Took so many long years to earn this hat',\n kind: 'layer',\n category: 'headwear',\n channels: ['main'],\n assetCid: 'bafkreic7pvfpb7fjgooiaianrc27mh7fwj5vkicre63l6x5hrzb4w36tcq',\n iconCid: 'bafkreigqt6lmx5crj3w7vc3bvuewarzdreg2doxyeerbxmhljhpeshjewm',\n enabled: true,\n unlock: [{ kind: 'hasDoctorate' }],\n },\n {\n id: 'weekend_shirt',\n title: 'Weekend Shirt',\n description: 'Fun shirt to wear when work is all finished',\n kind: 'layer',\n category: 'tops',\n channels: ['main', 'sub1', 'sub2'],\n assetCid: 'bafkreigifgpwkxvftiuzbjc6c2xz4xf2iv4bznbhu364e7rhvfmhosbak4',\n iconCid: 'bafkreieguco74wkabuyhs4sz6ec35nyywr7ikaw6et4coeezphnsnqqjui',\n enabled: true,\n unlock: [{ kind: 'hasRecord', collection: 'id.sifa.profile.volunteering' }],\n },\n {\n id: 'lab_coat',\n title: 'Lab Coat',\n description: 'Scientifically proven attire',\n kind: 'layer',\n category: 'tops',\n channels: ['main'],\n assetCid: 'bafkreiby4g6fgkmi65myv7tdblgb4jvqa3kgnrxvtkxlrtme55unuie4he',\n iconCid: 'bafkreifoddxk5tobgwadib5rxwjn67iind6me3swpvw4t5rbcauc5r4syy',\n enabled: true,\n unlock: [{ kind: 'hasExternalAccount', platforms: ['orcid'] }],\n },\n];\n","import { RPG_ITEMS, type RpgItem, type RpgUnlock } from './catalog.js';\n\n/**\n * Profile signals the unlock rules are checked against. Callers must pass\n * lowercase platform codes (e.g. 'github', 'orcid') and registry app ids (e.g. 'tangled').\n */\nexport interface RpgUnlockSignals {\n collections: readonly string[];\n externalPlatforms: readonly string[];\n activeAppIds: readonly string[];\n hasDoctorate: boolean;\n}\n\n/** One enabled catalog item and whether the signals earn it. */\nexport interface RpgUnlockResult {\n item: RpgItem;\n earned: boolean;\n}\n\nfunction matches(u: RpgUnlock, s: RpgUnlockSignals): boolean {\n switch (u.kind) {\n case 'hasRecord':\n return s.collections.includes(u.collection);\n case 'hasExternalAccount':\n return u.platforms.some((p) => s.externalPlatforms.includes(p));\n case 'usesApp':\n return s.activeAppIds.includes(u.appId);\n case 'hasDoctorate':\n return s.hasDoctorate;\n }\n}\n\n/** Evaluate every enabled item (ANY matching unlock earns it); disabled items are omitted. */\nexport function evaluateRpgUnlocks(\n signals: RpgUnlockSignals,\n items: readonly RpgItem[] = RPG_ITEMS,\n): RpgUnlockResult[] {\n return items\n .filter((item) => item.enabled)\n .map((item) => ({ item, earned: item.unlock.some((u) => matches(u, signals)) }));\n}\n","/** Base URL of rpg.actor. */\nexport const RPG_ACTOR_URL = 'https://rpg.actor';\n\n/**\n * Record key of the `equipment.rpg.give` Sifa writes for an item. rpg.actor\n * stores the accepted `equipment.rpg.item` under the same key, so this also\n * identifies the item in the player's own account.\n *\n * The DID is used as-is: AT Protocol record keys allow `A-Za-z0-9 . - _ : ~`\n * (https://atproto.com/specs/record-key), so the colons in `did:plc:` are\n * valid. The format is already live in written gift records; do not change it.\n */\nexport function rpgGiveRkey(itemId: string, recipientDid: string): string {\n return `sifa-${itemId}-${recipientDid}`;\n}\n\n/** The player's character page on rpg.actor, where pending gifts can be accepted. */\nexport function rpgActorCharacterUrl(handleOrDid: string): string {\n return `${RPG_ACTOR_URL}/${encodeURIComponent(handleOrDid.replace(/^@+/, ''))}`;\n}\n\n/** Deep link that opens the Wear action for an accepted Sifa item on the character page. */\nexport function rpgActorWearUrl(handleOrDid: string, itemId: string, recipientDid: string): string {\n return `${rpgActorCharacterUrl(handleOrDid)}?wear=${encodeURIComponent(rpgGiveRkey(itemId, recipientDid))}`;\n}\n"]}
|
package/dist/rpg/index.d.cts
CHANGED
|
@@ -24,8 +24,12 @@ declare const RpgItemSchema: z.ZodObject<{
|
|
|
24
24
|
kind: z.ZodEnum<{
|
|
25
25
|
layer: "layer";
|
|
26
26
|
held: "held";
|
|
27
|
+
overlay: "overlay";
|
|
27
28
|
}>;
|
|
28
29
|
category: z.ZodString;
|
|
30
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
31
|
+
assetCid: z.ZodString;
|
|
32
|
+
iconCid: z.ZodString;
|
|
29
33
|
unlock: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
30
34
|
kind: z.ZodLiteral<"hasRecord">;
|
|
31
35
|
collection: z.ZodEnum<{
|
|
@@ -48,8 +52,8 @@ declare const RpgItemSchema: z.ZodObject<{
|
|
|
48
52
|
type RpgItem = z.infer<typeof RpgItemSchema>;
|
|
49
53
|
type RpgUnlock = z.infer<typeof RpgUnlockSchema>;
|
|
50
54
|
/**
|
|
51
|
-
* The Sifa item catalog for rpg.actor.
|
|
52
|
-
* rpg.actor
|
|
55
|
+
* The Sifa item catalog for rpg.actor. Ids, titles, descriptions, kinds,
|
|
56
|
+
* categories, channels and image CIDs come from rpg.actor's item cores.
|
|
53
57
|
*/
|
|
54
58
|
declare const RPG_ITEMS: readonly RpgItem[];
|
|
55
59
|
|
package/dist/rpg/index.d.ts
CHANGED
|
@@ -24,8 +24,12 @@ declare const RpgItemSchema: z.ZodObject<{
|
|
|
24
24
|
kind: z.ZodEnum<{
|
|
25
25
|
layer: "layer";
|
|
26
26
|
held: "held";
|
|
27
|
+
overlay: "overlay";
|
|
27
28
|
}>;
|
|
28
29
|
category: z.ZodString;
|
|
30
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
31
|
+
assetCid: z.ZodString;
|
|
32
|
+
iconCid: z.ZodString;
|
|
29
33
|
unlock: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
30
34
|
kind: z.ZodLiteral<"hasRecord">;
|
|
31
35
|
collection: z.ZodEnum<{
|
|
@@ -48,8 +52,8 @@ declare const RpgItemSchema: z.ZodObject<{
|
|
|
48
52
|
type RpgItem = z.infer<typeof RpgItemSchema>;
|
|
49
53
|
type RpgUnlock = z.infer<typeof RpgUnlockSchema>;
|
|
50
54
|
/**
|
|
51
|
-
* The Sifa item catalog for rpg.actor.
|
|
52
|
-
* rpg.actor
|
|
55
|
+
* The Sifa item catalog for rpg.actor. Ids, titles, descriptions, kinds,
|
|
56
|
+
* categories, channels and image CIDs come from rpg.actor's item cores.
|
|
53
57
|
*/
|
|
54
58
|
declare const RPG_ITEMS: readonly RpgItem[];
|
|
55
59
|
|
package/package.json
CHANGED