SOURCE / PINNED RELEASE
Made of little things.
Napcraft
- Release
- ee47ac6a25df…
- Author-recorded commit
- 410dea87e109…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-52f9e22f5ce
Archive hash verified: 9e6e0cabb18d0d46…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import { identity, outbox } from '@napplet/sdk';
import { appDataCollection, type AppDataHost, type AppRecord } from '../docs/examples/app-data';
export type WorldListing = { code: string };
export type ListedWorld = AppRecord<WorldListing>;
/** Advertisements may point only to ordinary Napcraft codes, never external URLs. */
export function validateListing(value: unknown): WorldListing {
if (!value || typeof value !== 'object' || Array.isArray(value) ||
Object.keys(value).join(',') !== 'code') throw new Error('Invalid world listing.');
const code = (value as WorldListing).code;
if (typeof code !== 'string' || code.length > 300 || !/^NC1-[A-Za-z0-9_-]+$/.test(code))
throw new Error('Invalid world code in listing.');
let parts: unknown;
try { parts = JSON.parse(atob(code.slice(4).replaceAll('-', '+').replaceAll('_', '/'))); }
catch { throw new Error('Invalid world code in listing.'); }
if (!Array.isArray(parts) || parts.length !== 2 || typeof parts[0] !== 'string' ||
!/^[a-f0-9]{64}$/.test(parts[0]) || typeof parts[1] !== 'string' ||
!/^[A-Za-z0-9_-]{1,64}$/.test(parts[1])) throw new Error('Invalid world code in listing.');
return { code: 'NC1-' + btoa(JSON.stringify(parts)).replaceAll('+','-').replaceAll('/','_').replace(/=+$/,'') };
}
export async function listingId(code: string) {
const bytes = new TextEncoder().encode(validateListing({code}).code);
const digest = await crypto.subtle.digest('SHA-256', bytes);
return [...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,'0')).join('');
}
export function distinctWorlds(records: ListedWorld[], viewer = '') {
const byCode = new Map<string, ListedWorld>();
for (const record of records) {
if (!record.data || record.deleted) continue;
const old = byCode.get(record.data.code);
if (!old || (record.author===viewer && old.author!==viewer) ||
(old.author!==viewer && (record.createdAt>old.createdAt ||
(record.createdAt===old.createdAt && record.revision<old.revision)))) byCode.set(record.data.code,record);
}
return [...byCode.values()].sort((a,b)=>b.createdAt-a.createdAt || a.revision.localeCompare(b.revision));
}
export async function openWorldDirectory() {
// The shipped soyLI app-data helper observes this host-policy hint. SDK 0.24.4
// has no shell export; this is not an app-owned handshake or network path.
const injected = (globalThis as unknown as {napplet?:AppDataHost}).napplet;
if (!injected?.shell?.onReady) throw new Error('This host does not offer the public world list. You can still join with a code.');
return appDataCollection<WorldListing>({
collection:'worlds', schema:'napcraft.world-directory', version:1,
validate:validateListing, host:{shell:injected.shell,identity,outbox:{
query:(filters,options)=>outbox.query(filters as Parameters<typeof outbox.query>[0],options),
publish:(template,options)=>outbox.publish(template,options),
}},
});
}
export type WorldDirectory = Awaited<ReturnType<typeof openWorldDirectory>>;
export type ListingChange = Awaited<ReturnType<WorldDirectory['prepare']>>;
