This commit is contained in:
j3d1 2026-08-27 01:34:34 +02:00
parent f46eff65fd
commit d56784eb8d
8 changed files with 335 additions and 93 deletions

View file

@ -204,6 +204,22 @@ export function deserializeShortId(ints) {
return schema.interpret(fieldValues)
}
export function encodeDomainQualifiedShortId(domain, ints) {
return domain + ':' + encodeShortId(ints)
}
export function decodeDomainQualifiedShortId(text) {
const i = text.indexOf(':~')
if (i === -1) {
throw new Error("not a domain-qualified short id: expected '<domain>:~<token>'")
}
return {domain: text.slice(0, i), token: text.slice(i + 1), ints: decodeShortId(text.slice(i + 1))}
}
export function isDomainQualifiedShortId(text) {
return typeof text === 'string' && /^[^\s~]+:~/.test(text)
}
export function serializeShortId({kind, ...fieldValues}) {
const entry = Object.entries(SCHEMAS).find(([, s]) => s.name === kind)
if (!entry) {

View file

@ -1,4 +1,7 @@
import {encodeShortId, decodeShortId, deserializeShortId, serializeShortId} from '../short-id.js'
import {
encodeShortId, decodeShortId, deserializeShortId, serializeShortId,
encodeDomainQualifiedShortId, decodeDomainQualifiedShortId, isDomainQualifiedShortId
} from '../short-id.js'
test('encodes the worked example from docs/handles-and-shortids.md', () => {
const token = encodeShortId([0, 7, 42])
@ -108,3 +111,34 @@ test('rejects a missing field', () => {
test('rejects a negative field value', () => {
expect(() => encodeShortId([0, -1, 42])).toThrow()
})
test('encodes a Domain-Qualified Short ID as "<domain>:<token>"', () => {
expect(encodeDomainQualifiedShortId('toolsheddomain.tld', [0, 7, 42])).toBe('toolsheddomain.tld:~DyU')
})
test('decodes a Domain-Qualified Short ID back into its domain and ints', () => {
const decoded = decodeDomainQualifiedShortId('toolsheddomain.tld:~DyU')
expect(decoded.domain).toBe('toolsheddomain.tld')
expect(decoded.token).toBe('~DyU')
expect(decoded.ints).toEqual([0, 7, 42])
})
test('round-trips a Domain-Qualified Short ID through encode/decode', () => {
const named = {kind: 'storage_location', owner_identity_id: 3, storage_location_id: 1000}
const encoded = encodeDomainQualifiedShortId('example.com', serializeShortId(named))
const {domain, ints} = decodeDomainQualifiedShortId(encoded)
expect(domain).toBe('example.com')
expect(deserializeShortId(ints)).toEqual(named)
})
test('rejects a Domain-Qualified Short ID missing the "~" after the domain', () => {
expect(() => decodeDomainQualifiedShortId('toolsheddomain.tldDyU')).toThrow()
expect(() => decodeDomainQualifiedShortId('~DyU')).toThrow()
})
test('isDomainQualifiedShortId tells a "<domain>:~token" apart from a bare token', () => {
expect(isDomainQualifiedShortId('toolsheddomain.tld:~DyU')).toBe(true)
expect(isDomainQualifiedShortId('~DyU')).toBe(false)
expect(isDomainQualifiedShortId('alice@example.com:i42')).toBe(false)
expect(isDomainQualifiedShortId('not a short id at all')).toBe(false)
})

View file

@ -73,7 +73,7 @@
</div>
<div class="btn-group mt-2">
<button class="btn btn-danger btn-sm"
@click="deleteStorageLocation(location.id)">Delete
@click="deleteStorageLocation(location)">Delete
</button>
<router-link :to="`${locationRoute(location)}/edit`"
class="btn btn-primary btn-sm">Edit