Skip to content

Commit

Permalink
fix(preset): types inference
Browse files Browse the repository at this point in the history
  • Loading branch information
JiLiZART committed Apr 26, 2024
1 parent 9e53c5d commit 7e37767
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 60 deletions.
69 changes: 23 additions & 46 deletions packages/bbob-preset/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,87 +1,64 @@
import type {
BBobCoreTagNodeTree,
BbobPluginOptions,
BBobPluginFunction,
BBobPluginOptions,
} from "@bbob/core";
import { isTagNode } from "@bbob/plugin-helper";
import type {
PresetFactory,
PresetExtendCallback,
PresetFactoryOptions,
PresetOptions,
PresetTagsDefinition,
ProcessorFunction,
} from "./types";

function process<Name extends string = string>(
tags: PresetTagsDefinition<Name>,
export function process<Tags extends PresetTagsDefinition = PresetTagsDefinition, Options extends PresetOptions = PresetOptions>(
tags: Tags,
tree: BBobCoreTagNodeTree,
core: BbobPluginOptions,
options: PresetFactoryOptions = {}
core: BBobPluginOptions,
options: Options
) {
return tree.walk((node) => {
if (isTagNode(node) && typeof tags[node.tag] === "function") {
if (isTagNode(node)) {
const tag = node.tag;
const tagCallback = tags[tag];

return tagCallback(node, core, options);
if (typeof tagCallback === "function") {
return tagCallback(node, core, options);
}
}

return node;
});
}

export type ProcessorFunction = typeof process;

export type ProcessorReturnType = ReturnType<ProcessorFunction>;

export interface PresetExecutor<
TagName extends string = string,
AttrValue = unknown
> extends BBobPluginFunction {
(tree: BBobCoreTagNodeTree, core?: BbobPluginOptions): ProcessorReturnType;
options: PresetOptions;
}

export interface PresetFactory<
TagName extends string = string,
AttrValue = unknown,
Names extends string = string
> {
(opts?: PresetOptions): PresetExecutor;
options?: PresetOptions;
extend: (
cb: PresetExtendCallback<Names>
) => PresetFactory<TagName, AttrValue, Names>;
}

/**
* Create a preset plugin for @bbob/core
*/
function createPreset<Names extends string = string>(
defTags: PresetTagsDefinition<Names>,
processor: ProcessorFunction = process
function createPreset<Tags extends PresetTagsDefinition = PresetTagsDefinition, RootOptions extends PresetOptions = PresetOptions,>(
defTags: Tags,
processor: ProcessorFunction<Tags> = process
) {
const presetFactory: PresetFactory = (opts: PresetOptions = {}) => {
const presetFactory: PresetFactory<typeof defTags, RootOptions> = <Options extends RootOptions>(opts: Options) => {
presetFactory.options = Object.assign(presetFactory.options || {}, opts);

function presetExecutor(
tree: BBobCoreTagNodeTree,
core: BbobPluginOptions
core: BBobPluginOptions
) {
return processor(defTags, tree, core, presetFactory.options);
return processor(defTags, tree, core, presetFactory.options || {});
}

presetExecutor.options = presetFactory.options;
presetExecutor.options = presetFactory.options as Options;

return presetExecutor;
};

presetFactory.extend = function presetExtend<ExtendNames extends string>(
callback: PresetExtendCallback<Names & ExtendNames>
presetFactory.extend = function presetExtend<NewTags extends PresetTagsDefinition = PresetTagsDefinition>(
callback: PresetExtendCallback<Tags, NewTags, RootOptions>
) {
return createPreset(
callback(defTags, presetFactory.options || {}),
processor
);
const newTags = callback(defTags, presetFactory.options)

return createPreset<typeof newTags, RootOptions>(newTags, processor as unknown as ProcessorFunction<NewTags>);
};

return presetFactory;
Expand Down
46 changes: 36 additions & 10 deletions packages/bbob-preset/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
import type { TagNodeObject } from "@bbob/plugin-helper";
import type { BbobPluginOptions } from "@bbob/core";
import type { BBobCoreTagNodeTree, BBobPluginFunction, BBobPluginOptions } from "@bbob/core";
import type { process } from "./preset";

export type PresetFactoryOptions = Record<string, unknown>
type PartialRecord<K extends keyof any, T> = Partial<Record<K, T>>

export type PresetTagFunction<Node extends object = TagNodeObject> = (
node: Node,
core: BbobPluginOptions,
options: PresetFactoryOptions
) => Node

export type PresetTagsDefinition<Name extends string = string> = Record<Name | string, PresetTagFunction>
export type PresetTagsDefinition<Key extends string = string> = PartialRecord<Key, PresetTagFunction>

export type PresetOptions = Record<string, unknown>
export type PresetExtendCallback<Names extends string> = (defTags: PresetTagsDefinition<Names>, options: PresetOptions) => PresetTagsDefinition<Names>

export type ProcessorFunction<Tags extends PresetTagsDefinition = PresetTagsDefinition> = typeof process<Tags>;

export type ProcessorReturnType<Tags extends PresetTagsDefinition = PresetTagsDefinition> = ReturnType<ProcessorFunction<Tags>>;

export interface PresetTagFunction<Node extends TagNodeObject = TagNodeObject, Options extends PresetOptions = PresetOptions> {
(
node: Node,
data: BBobPluginOptions,
options: Options
): Node
}

export interface PresetExtendCallback<Tags, NewTags = Tags, Options extends PresetOptions = PresetOptions> {
(defTags: Tags, options?: Options): NewTags
}

export interface PresetExecutor<Tags extends PresetTagsDefinition = PresetTagsDefinition, Options extends PresetOptions = PresetOptions> extends BBobPluginFunction {
(tree: BBobCoreTagNodeTree, core?: BBobPluginOptions): ProcessorReturnType<Tags>;
options: Options;
}

export interface PresetFactory<
Tags extends PresetTagsDefinition = PresetTagsDefinition,
RootOptions extends PresetOptions = PresetOptions,
> {
<Options extends RootOptions>(opts: Options): PresetExecutor<Tags, Options>;
options?: RootOptions;
extend: <NewTags extends PresetTagsDefinition = PresetTagsDefinition>(
cb: PresetExtendCallback<Tags, NewTags, RootOptions>
) => PresetFactory<NewTags, RootOptions>;
}
9 changes: 5 additions & 4 deletions packages/bbob-preset/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import { createPreset, PresetTagsDefinition } from '../src';
import { BBobCoreOptions, createTree } from '@bbob/core'

describe('@bbob/preset', () => {
const presetFactory = (defTags: PresetTagsDefinition) => {
const presetFactory = <Tags extends PresetTagsDefinition = PresetTagsDefinition>(defTags: Tags) => {
const processor = jest.fn((tags, tree, core, options) => tags)
const preset = createPreset<Tags>(defTags, processor)

return {
preset: createPreset(defTags, processor),
preset,
processor,
core: {} as BBobCoreOptions
}
}

test('create', () => {
const defTags = { test: () => 'test' }
const defTags = { test: () => ({ tag: 'test' }) }
const options = { foo: 'bar' }
const tree = createTree([], {})
const { preset, processor, core } = presetFactory(defTags);
const { preset, processor } = presetFactory(defTags);

expect(preset.extend)
.toBeDefined();
Expand Down

0 comments on commit 7e37767

Please sign in to comment.