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 87 88 89 90 91 92 93 94 | 3x 14x 19x 2x 4x 12x 3x 9x 9x 14x 14x 15x 15x 15x 15x 15x 14x 14x 9x | import { assert } from '@metamask/superstruct';
import type { Infer } from '@metamask/superstruct';
import { platformConfigStruct } from './capabilities/index.ts';
import type {
PlatformFactory,
PlatformConfig,
Platform,
Capability,
CapabilityName,
CapabilityFactories,
PlatformOptions,
} from './types.ts';
const validatePlatformConfig = (
config: Infer<typeof platformConfigStruct>,
known: CapabilityName[],
): void => {
const configured = Object.keys(config) as CapabilityName[];
if (configured.some((name) => !known.includes(name))) {
throw new Error(
`Config provided entry for unregistered capability: ${configured.find((name) => !known.includes(name))}`,
{ cause: { configured, known } },
);
}
assert(config, platformConfigStruct);
};
/**
* Creates a platform factory from capability factories
*
* @param capabilityFactories - The capability factories to use
* @returns A platform factory function
*/
export const makePlatformFactory = <
Factories extends Partial<CapabilityFactories>,
>(
capabilityFactories: Factories,
): PlatformFactory<CapabilityName, Factories> => {
const knownCapabilities = Object.keys(
capabilityFactories,
) as CapabilityName[];
/**
* Creates a platform with the specified capabilities
*
* @param config - The configuration for the platform
* @param options - The options for the platform
* @returns An object with the specified capabilities
*/
const createPlatform = async (
config: Partial<PlatformConfig>,
options?: Partial<PlatformOptions<Factories>>,
): Promise<Platform<keyof typeof config>> => {
validatePlatformConfig(config, knownCapabilities);
const capabilityEntries = Object.entries(config).map(
([name, capabilityConfig]) => {
const factory =
capabilityFactories[name as (typeof knownCapabilities)[number]];
Iif (!factory) {
throw new Error(`No factory found for capability: ${name}`);
}
const capabilityOptions = options?.[name as keyof typeof config] ?? {};
// The `any` type assertion is necessary here because TypeScript cannot infer that:
// 1. The factory for 'name' is specifically typed for that capability
// 2. The config for 'name' matches the factory's expected config type
// 3. The generic constraints align between the factory and config
// This is a limitation of TypeScript's type system with dynamic property access
const capability = factory(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
capabilityConfig as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
capabilityOptions as any,
);
return [name, harden(capability)] as [
keyof typeof config,
Capability<keyof typeof config>,
];
},
);
const platform = Object.fromEntries(capabilityEntries) as Platform<
keyof typeof config
>;
return harden(platform);
};
return harden(createPlatform);
};
|