@ucanto/core
Version:
98 lines (88 loc) • 2.53 kB
JavaScript
import * as API from '@ucanto/interface'
import * as Schema from './schema.js'
import * as DID from '@ipld/dag-ucan/did'
/**
* @template {string} Method
* @extends {Schema.API<API.DID<Method> & API.URI<"did:">, string, void|Method>}
*/
class DIDSchema extends Schema.API {
/**
* @param {string} source
* @param {void|Method} method
*/
readWith(source, method) {
const prefix = method ? `did:${method}:` : `did:`
if (!source.startsWith(prefix)) {
return Schema.error(`Expected a ${prefix} but got "${source}" instead`)
} else {
return { ok: /** @type {API.DID<Method>} */ (source) }
}
}
}
const schema = Schema.string().refine(new DIDSchema())
export const did = () => schema
/**
*
* @param {unknown} input
*/
export const read = input => schema.read(input)
/**
* @template {string} Method
* @param {{method?: Method}} options
*/
export const match = (options = {}) =>
/** @type {Schema.Schema<API.DID<Method> & API.URI<"did:">>} */ (
Schema.string().refine(new DIDSchema(options.method))
)
/**
* Create a DID string from any input (or throw)
* @param {unknown} input
*/
export const from = input => match({}).from(input)
/**
* @template {string} Method
* @extends {Schema.API<API.DID<Method> & API.URI<"did:">, unknown, void|Method>}
*/
class DIDBytesSchema extends Schema.API {
/**
* @param {unknown} source
* @param {void|Method} method
*/
readWith(source, method) {
if (!(source instanceof Uint8Array)) {
return Schema.typeError({ expect: 'Uint8Array', actual: source })
}
let did
try {
did = DID.decode(source).did()
} catch (err) {
return Schema.error(`Unable to parse bytes as did: ${err}`)
}
const prefix = method ? `did:${method}:` : `did:`
if (!did.startsWith(prefix)) {
return Schema.error(`Expected a ${prefix} but got "${did}" instead`)
} else {
return { ok: /** @type {API.DID<Method>} */ (did) }
}
}
}
const schemaBytes = new DIDBytesSchema()
export const didBytes = () => schemaBytes
/**
*
* @param {unknown} input
*/
export const readBytes = input => schemaBytes.read(input)
/**
* @template {string} Method
* @param {{method?: Method}} options
*/
export const matchBytes = (options = {}) =>
/** @type {Schema.Schema<API.DID<Method> & API.URI<"did:">>} */ (
new DIDBytesSchema(options.method)
)
/**
* Create a DID string from any input (or throw)
* @param {unknown} input
*/
export const fromBytes = input => matchBytes({}).from(input)