Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 6x 6x 91x 91x 6x 95x 1x 94x 2x 92x 1x 91x 1x 90x 6x 77x 6x 8x 6x 101x 6x 95x 101x | /**
* MetadataSpec constructors and evaluation helpers.
*/
import type { MetadataSpec } from './types.ts';
const metadataPlainObjectHint =
'Sheaf metadata must be a plain object; use e.g. { value: myValue } if you need to attach a primitive.';
const isPlainObjectRecord = (value: object): boolean => {
const proto = Object.getPrototypeOf(value);
return proto === null || proto === Object.prototype;
};
/**
* Normalize evaluated metadata: empty sentinel is `{}`; invalid shapes throw.
*
* @param raw - Result from constant value or callable, before validation.
* @returns A plain object suitable for candidate metadata.
*/
const normalizeEvaluatedSheafMetadata = (
raw: unknown,
): Record<string, unknown> => {
if (raw === undefined || raw === null) {
return {};
}
if (typeof raw !== 'object') {
throw new Error(
`sheafify: metadata cannot be a primitive (${typeof raw}). ${metadataPlainObjectHint}`,
);
}
if (Array.isArray(raw)) {
throw new Error(
`sheafify: metadata cannot be an array. ${metadataPlainObjectHint}`,
);
}
if (!isPlainObjectRecord(raw)) {
throw new Error(
`sheafify: metadata must be a plain object. ${metadataPlainObjectHint}`,
);
}
return raw as Record<string, unknown>;
};
/**
* Wrap a static value as a constant metadata spec.
*
* @param value - The static metadata value.
* @returns A constant MetadataSpec wrapping the value.
*/
export const constant = <M extends Record<string, unknown>>(
value: M,
): MetadataSpec<M> => harden({ kind: 'constant', value });
/**
* Wrap a live function as a callable metadata spec.
*
* @param fn - Function from invocation args to metadata value.
* @returns A callable metadata spec.
*/
export const callable = <M extends Record<string, unknown>>(
fn: (args: unknown[]) => M,
): MetadataSpec<M> => harden({ kind: 'callable', fn });
/**
* Evaluate a metadata spec against the invocation args.
*
* Missing spec yields `{}` (no metadata). Callable/constant results must be plain objects;
* `undefined`/`null` from the producer normalize to `{}`. Primitives, arrays, and non-plain
* objects throw with guidance to use an explicit record such as `{ value: myValue }`.
*
* @param spec - The spec to evaluate, or undefined.
* @param args - The invocation arguments.
* @returns The evaluated metadata object (possibly empty).
*/
export const evaluateMetadata = <MetaData extends Record<string, unknown>>(
spec: MetadataSpec<MetaData> | undefined,
args: unknown[],
): MetaData => {
if (spec === undefined) {
return {} as MetaData;
}
const raw = spec.kind === 'constant' ? spec.value : spec.fn(args);
return normalizeEvaluatedSheafMetadata(raw) as MetaData;
};
|