SOURCE / PINNED RELEASE
Made of little things.
Powder Tool V600Billion
- Release
- 142767edcab8…
- Author-recorded commit
- 6d92971effd0…
- License
- LICENSE
- Author’s source reference
- nostr://npub1fllw8kw0thjj55wds0uugcnp5kej2nfxd36eruq39d56wwz8r44q5q78wj/wss%3A%2F%2Fgit.napplet.soy%2F/powder-toy
Archive hash verified: ed7d6a8ea7083197…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
/**
* src/napplet.js against stand-ins for window.napplet's outbox: a host that
* signs only its own record format (napplet.soy's outbox.publish) is reported
* in words a player can act on, whether it answers `ok: false` or throws;
* other host errors pass through unchanged; reads go through outbox.query and
* outbox.subscribe and hand back raw events.
*/
import assert from 'node:assert/strict';
import test from 'node:test';
import { OWN_FORMAT_ONLY_MESSAGE, collect, publish, watch } from '../src/napplet.js';
const withHost = (napplet) => { globalThis.window = { napplet }; };
const refusing = (error) => ({ outbox: { publish: async () => ({ ok: false, error }) } });
const throwing = (message) => ({ outbox: { publish: async () => { throw new Error(message); } } });
const event = { id: 'a'.repeat(64), kind: 7, content: '+', tags: [], pubkey: 'b'.repeat(64), created_at: 1, sig: 'c'.repeat(128) };
test('a host that publishes only its own records is explained, not quoted', async () => {
// Word for word what napplet.soy's host answers (packages/runtime/src/app-data-session.ts there).
withHost(refusing('app-data-invalid-request: only documented kind-30078 records and configured relay destinations can be published.'));
await assert.rejects(publish({ kind: 7, content: '+', tags: [] }), { message: OWN_FORMAT_ONLY_MESSAGE });
withHost(throwing('not-signed-in: connect a viewer identity to publish app data.'));
await assert.rejects(publish({ kind: 1111, content: 'hi', tags: [] }), { message: OWN_FORMAT_ONLY_MESSAGE });
});
test('other refusals pass through unchanged, and a signed event comes back', async () => {
withHost(refusing('outbox:write denied'));
await assert.rejects(publish({ kind: 7, content: '+', tags: [] }), { message: 'outbox:write denied' });
withHost({ outbox: { publish: async () => ({ ok: true, event, eventId: event.id }) } });
assert.equal(await publish({ kind: 7, content: '+', tags: [] }), event);
withHost({ outbox: { publish: async () => ({ ok: true }) } });
await assert.rejects(publish({ kind: 7, content: '+', tags: [] }), { message: 'The host did not return the signed event.' });
withHost({});
await assert.rejects(publish({ kind: 7, content: '+', tags: [] }), { message: 'Sharing is not available here.' });
delete globalThis.window;
});
test('reads go through outbox.query and outbox.subscribe', async () => {
const asked = [];
let listener = null;
let closed = false;
withHost({
outbox: {
query: async (filters, options) => { asked.push({ filters, options }); return { events: [{ event }, { event: { nope: true } }] }; },
subscribe: (filters) => ({ on: (kind, handler) => { if (kind === 'event') listener = handler; }, close: () => { closed = true; } }),
},
});
assert.deepEqual(await collect({ kinds: [7] }), [event]);
assert.deepEqual(asked, [{ filters: [{ kinds: [7] }], options: { timeoutMs: 4000 } }]);
const seen = [];
const stop = watch([{ kinds: [7] }], (item) => seen.push(item));
listener({ event });
listener({ event }); // the same event twice counts once
assert.deepEqual(seen, [event]);
stop();
assert.equal(closed, true);
withHost({});
assert.deepEqual(await collect({ kinds: [7] }), [], 'no outbox: nothing to read, no error');
delete globalThis.window;
});
