chore: initial commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import {types} from 'node:util';
|
||||
|
||||
export const valid_plugin_name = (value: unknown): value is string =>
|
||||
typeof value === 'string' && /^[a-zA-Z0-9_-]+$/.test(value);
|
||||
export const valid_plugin_path = (value: unknown): value is string =>
|
||||
typeof value === 'string' && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(value);
|
||||
|
||||
export function plain_plugin_object(value: unknown): value is Record<string, unknown> {
|
||||
if (!value || typeof value !== 'object' || types.isProxy(value)) return false;
|
||||
const prototype = Object.getPrototypeOf(value);
|
||||
if (!prototype || types.isProxy(prototype)) return false;
|
||||
const constructor = Object.getOwnPropertyDescriptor(prototype, 'constructor');
|
||||
// Accept ordinary objects from other realms, but never custom prototypes.
|
||||
if (Object.getPrototypeOf(prototype) !== null || !constructor
|
||||
|| typeof constructor.value !== 'function'
|
||||
|| types.isProxy(constructor.value) || constructor.value.prototype !== prototype
|
||||
|| Function.prototype.toString.call(constructor.value) !== 'function Object() { [native code] }') return false;
|
||||
return Reflect.ownKeys(value).every(key => typeof key === 'string'
|
||||
&& Object.getOwnPropertyDescriptor(value, key)?.enumerable
|
||||
&& Object.hasOwn(Object.getOwnPropertyDescriptor(value, key)!, 'value'));
|
||||
}
|
||||
|
||||
export function valid_plugin_config(value: unknown): value is Record<string, unknown> {
|
||||
if (!plain_plugin_object(value)) return false;
|
||||
return Object.values(value).every(item => {
|
||||
if (item === null || typeof item === 'string' || typeof item === 'boolean') return true;
|
||||
if (typeof item === 'number') return Number.isFinite(item);
|
||||
if (!Array.isArray(item) || types.isProxy(item)) return false;
|
||||
const prototype = Object.getPrototypeOf(item);
|
||||
if (!prototype || types.isProxy(prototype)) return false;
|
||||
const constructor = Object.getOwnPropertyDescriptor(prototype, 'constructor');
|
||||
if (!constructor || typeof constructor.value !== 'function'
|
||||
|| types.isProxy(constructor.value) || constructor.value.prototype !== prototype
|
||||
|| Function.prototype.toString.call(constructor.value) !== 'function Array() { [native code] }') return false;
|
||||
const keys = Reflect.ownKeys(item);
|
||||
return keys.length === item.length + 1 && keys.every(key => key === 'length'
|
||||
|| typeof key === 'string' && /^(0|[1-9]\d*)$/.test(key)
|
||||
&& Object.hasOwn(Object.getOwnPropertyDescriptor(item, key)!, 'value'))
|
||||
&& Array.from(item).every(value => typeof value === 'string' || typeof value === 'number' && Number.isFinite(value));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user