diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2025-07-09 23:29:06 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2025-08-21 19:42:09 -0400 |
| commit | a5326a67e37d9f1aee740f7b3d46345f3bcda419 (patch) | |
| tree | 18a1eff075e12c60e2bc2400703b9ad2cc67e7d4 | |
| parent | 4624f4dbebf5dd1ed4dc5168573537459b9a115e (diff) | |
Factor data-to-JSON-string construction out of stitches.
This is a recurring and nameable operation; let's give it a name before we use it further.
| -rw-r--r-- | ui/lib/swatch/derive.js | 6 | ||||
| -rw-r--r-- | ui/lib/swatch/json.js | 7 | ||||
| -rw-r--r-- | ui/lib/swatch/json.test.js | 36 | ||||
| -rw-r--r-- | ui/lib/swatch/setup.js | 0 | ||||
| -rw-r--r-- | ui/routes/(swatch)/.swatch/ConversationList/+page.svelte | 32 | ||||
| -rw-r--r-- | ui/routes/(swatch)/.swatch/Invites/+page.svelte | 8 | ||||
| -rw-r--r-- | ui/routes/(swatch)/.swatch/swatch/EventLog/+page.svelte | 13 |
7 files changed, 67 insertions, 35 deletions
diff --git a/ui/lib/swatch/derive.js b/ui/lib/swatch/derive.js index 85547e8..22ceb13 100644 --- a/ui/lib/swatch/derive.js +++ b/ui/lib/swatch/derive.js @@ -5,16 +5,12 @@ function tryDerive(args, func, fallback) { try { return func(...args); } catch (e) { - console.debug('deriver threw exception', e, func, args); return fallback; } } // A "deriver" is a function that never raises; if the underlying function would raise, the // corresponding deriver instead returns a fallback value (or `undefined`). -export function makeDeriver(func, fallback) { +export function makeDeriver(func, fallback = undefined) { return (...args) => tryDerive(args, func, fallback); } - -// Some widely-used derivers, for convenience. -export const json = makeDeriver(JSON.parse); diff --git a/ui/lib/swatch/json.js b/ui/lib/swatch/json.js new file mode 100644 index 0000000..3ebbc0d --- /dev/null +++ b/ui/lib/swatch/json.js @@ -0,0 +1,7 @@ +import { makeDeriver } from '$lib/swatch/derive.js'; + +export const decode = makeDeriver(JSON.parse); + +export function encode(value) { + return JSON.stringify(value, /* replacer */ null, /* space */ 2); +} diff --git a/ui/lib/swatch/json.test.js b/ui/lib/swatch/json.test.js new file mode 100644 index 0000000..e01017d --- /dev/null +++ b/ui/lib/swatch/json.test.js @@ -0,0 +1,36 @@ +import * as json from './json.js'; +import { expect, describe, it } from 'vitest'; + +describe('encode', async () => { + it('converts atoms', async () => { + expect(json.encode(0)).toStrictEqual('0'); + expect(json.encode('hello')).toStrictEqual('"hello"'); + expect(json.encode(null)).toStrictEqual('null'); + expect(json.encode(true)).toStrictEqual('true'); + }); + + it('converts lists with indentation', async () => { + expect(json.encode([])).toStrictEqual('[]'); + expect(json.encode(['hello', 'world'])).toStrictEqual('[\n "hello",\n "world"\n]'); + }); + + it('converts objects with indentation', async () => { + expect(json.encode({})).toStrictEqual('{}'); + expect(json.encode({ field: 'value' })).toStrictEqual('{\n "field": "value"\n}'); + }); +}); + +describe('decode', async () => { + it('converts valid json values', async () => { + expect(json.decode('0')).toStrictEqual(0); + expect(json.decode('null')).toStrictEqual(null); + expect(json.decode('{}')).toStrictEqual({}); + expect(json.decode('[1, 2, "3"]')).toStrictEqual([1, 2, '3']); + }); + + it('converts invalid json to `undefined`', async () => { + expect(json.decode('')).toBeUndefined(); + expect(json.decode('{"foo":')).toBeUndefined(); + expect(json.decode('arbitrary nonsense')).toBeUndefined(); + }); +}); diff --git a/ui/lib/swatch/setup.js b/ui/lib/swatch/setup.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ui/lib/swatch/setup.js diff --git a/ui/routes/(swatch)/.swatch/ConversationList/+page.svelte b/ui/routes/(swatch)/.swatch/ConversationList/+page.svelte index ef0c8a9..b0bc97a 100644 --- a/ui/routes/(swatch)/.swatch/ConversationList/+page.svelte +++ b/ui/routes/(swatch)/.swatch/ConversationList/+page.svelte @@ -1,27 +1,23 @@ <script> - import { json } from '$lib/swatch/derive.js'; + import * as json from '$lib/swatch/json.js'; import ConversationList from '$lib/components/ConversationList.svelte'; let conversationsInput = $state( - JSON.stringify( - [ - { - id: 'Czero', - name: 'A long conversation', - hasUnreads: false, - }, - { - id: 'Cone', - name: 'A shorter conversation', - hasUnreads: true, - }, - ], - /* replacer */ null, - /* space */ 2, - ), + json.encode([ + { + id: 'Czero', + name: 'A long conversation', + hasUnreads: false, + }, + { + id: 'Cone', + name: 'A shorter conversation', + hasUnreads: true, + }, + ]), ); - let conversations = $derived(json(conversationsInput)); + let conversations = $derived(json.decode(conversationsInput)); let active = $state(null); </script> diff --git a/ui/routes/(swatch)/.swatch/Invites/+page.svelte b/ui/routes/(swatch)/.swatch/Invites/+page.svelte index 8c24627..bc4bdb1 100644 --- a/ui/routes/(swatch)/.swatch/Invites/+page.svelte +++ b/ui/routes/(swatch)/.swatch/Invites/+page.svelte @@ -1,14 +1,12 @@ <script> - import { json } from '$lib/swatch/derive.js'; + import * as json from '$lib/swatch/json.js'; import EventCapture from '$lib/swatch/event-capture.svelte.js'; import EventLog from '$lib/components/swatch/EventLog.svelte'; import Invites from '$lib/components/Invites.svelte'; - let invitesInput = $state( - JSON.stringify([{ id: 'Iaaaa' }, { id: 'Ibbbb' }], /* replacer */ null, /* space */ 2), - ); - let invites = $derived(json(invitesInput)); + let invitesInput = $state(json.encode([{ id: 'Iaaaa' }, { id: 'Ibbbb' }])); + let invites = $derived(json.decode(invitesInput)); let capture = $state(new EventCapture()); const createInvite = capture.on('createInvite'); diff --git a/ui/routes/(swatch)/.swatch/swatch/EventLog/+page.svelte b/ui/routes/(swatch)/.swatch/swatch/EventLog/+page.svelte index a751ca3..eae0838 100644 --- a/ui/routes/(swatch)/.swatch/swatch/EventLog/+page.svelte +++ b/ui/routes/(swatch)/.swatch/swatch/EventLog/+page.svelte @@ -1,17 +1,16 @@ <script> import EventCapture from '$lib/swatch/event-capture.svelte.js'; - import { json } from '$lib/swatch/derive.js'; + import * as json from '$lib/swatch/json.js'; import EventLog from '$lib/components/swatch/EventLog.svelte'; let eventsInput = $state( - JSON.stringify( - [{ event: 'example', args: ['argument a', 'argument b'] }], - /* replacer */ null, - /* space */ 2, - ), + json.encode([ + { event: 'firstExample', args: ['argument a', 'argument b'] }, + { event: 'secondExample', args: ['argument 1'] }, + ]), ); - let events = $derived(json(eventsInput)); + let events = $derived(json.decode(eventsInput)); let capture = $state(new EventCapture()); const clear = capture.on('clear'); |
