Skip to content

Commit a53c70c

Browse files
committed
♻️ 对defu代码进行了fork,主动进行改造
1 parent 2b7807a commit a53c70c

File tree

11 files changed

+193
-20
lines changed

11 files changed

+193
-20
lines changed

deno.lock

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nodekit/deno.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "@gaubee/nodekit",
3-
"version": "0.11.3",
3+
"version": "0.12.0",
44
"exports": {
55
"./colors": "./src/colors.ts",
66
"./config_file": "./src/config_file.ts",
7-
"./config": "./src/config.ts",
7+
"./merge-config": "./src/merge-config/mod.ts",
88
"./markdown_file": "./src/markdown_file.ts",
99
"./fs": "./src/fs.ts",
1010
"./git": "./src/git/index.ts",

nodekit/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"dependencies": {
66
"@inquirer/prompts": "^7.5.3",
77
"dax-sh": "^0.43.2",
8-
"defu": "^6.1.4",
98
"gray-matter": "^4.0.3",
109
"ignore": "^7.0.5",
1110
"minimatch": "^10.0.3",

nodekit/src/config.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

nodekit/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export * from "./colors.ts";
22
export * from "./config_file.ts";
3-
export * from './config.ts'
3+
export * from './merge-config/mod.ts'
44
export * from "./fs.ts";
55
export * from "./git/index.ts";
66
export * from "./ignore.ts";

nodekit/src/merge-config/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
参考 https://github.com/unjs/defu
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Forked from unjs/defu (MIT)
2+
import {obj_assign_props} from "@gaubee/util/object";
3+
import type {MergeConfig} from "./types.ts";
4+
import {isPlainObject} from "./utils.ts";
5+
6+
// Base function to apply defaults
7+
function _merge_config<T>(baseObject: T, defaults: any, namespace = ".", merger?: MergeConfig.Merger): T {
8+
if (!isPlainObject(defaults)) {
9+
return _merge_config(baseObject, {}, namespace, merger);
10+
}
11+
12+
const object = Object.assign({}, defaults);
13+
14+
for (const key in baseObject) {
15+
if (key === "__proto__" || key === "constructor") {
16+
continue;
17+
}
18+
19+
const value = baseObject[key];
20+
21+
if (value === null || value === undefined) {
22+
continue;
23+
}
24+
25+
if (merger && merger(object, key, value, namespace)) {
26+
continue;
27+
}
28+
29+
if (Array.isArray(value) && Array.isArray(object[key])) {
30+
object[key] = [...value, ...object[key]];
31+
} else if (isPlainObject(value) && isPlainObject(object[key])) {
32+
object[key] = _merge_config(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
33+
} else {
34+
object[key] = value;
35+
}
36+
}
37+
38+
return object;
39+
}
40+
41+
// Create defu wrapper with optional merger and multi arg support
42+
export function createMergeConfig(merger?: MergeConfig.Merger): MergeConfig.MergeFn {
43+
return (...args) =>
44+
// eslint-disable-next-line unicorn/no-array-reduce
45+
args.reduce((p, c) => _merge_config(p, c, "", merger), {} as any);
46+
}
47+
48+
// Custom version with function merge support
49+
const defuFn = createMergeConfig((object, key, currentValue) => {
50+
if (object[key] !== undefined && typeof currentValue === "function") {
51+
object[key] = currentValue(object[key]);
52+
return true;
53+
}
54+
});
55+
56+
// Custom version with function merge support only for defined arrays
57+
const defuArrayFn = createMergeConfig((object, key, currentValue) => {
58+
if (Array.isArray(object[key]) && typeof currentValue === "function") {
59+
object[key] = currentValue(object[key]);
60+
return true;
61+
}
62+
});
63+
64+
// Standard version
65+
export const mergeConfig: MergeConfig.Instance = obj_assign_props(createMergeConfig(), {
66+
fn: defuFn,
67+
arrayFn: defuArrayFn,
68+
create: createMergeConfig,
69+
});

nodekit/src/merge-config/mod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './merge-config.ts'
2+
export * from './types.ts'

nodekit/src/merge-config/types.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Forked from unjs/defu (MIT)
2+
export namespace MergeConfig {
3+
export type Input = Record<string | number | symbol, any>;
4+
export type IgnoredInput = boolean | number | null | any[] | Record<never, any> | undefined;
5+
6+
export type Merger = <T extends Input, K extends keyof T>(object: T, key: keyof T, value: T[K], namespace: string) => any;
7+
8+
type nullish = null | undefined | void;
9+
10+
export type MergeObjects<Destination extends Input, Defaults extends Input> = Destination extends Defaults
11+
? Destination
12+
: Omit<Destination, keyof Destination & keyof Defaults> &
13+
Omit<Defaults, keyof Destination & keyof Defaults> & {
14+
-readonly [Key in keyof Destination & keyof Defaults]: Destination[Key] extends nullish
15+
? Defaults[Key] extends nullish
16+
? nullish
17+
: Defaults[Key]
18+
: Defaults[Key] extends nullish
19+
? Destination[Key]
20+
: Merge<Destination[Key], Defaults[Key]>; // eslint-disable-line no-use-before-define
21+
};
22+
23+
export type Merged<S extends Input, D extends Array<Input | IgnoredInput>> = D extends [infer F, ...infer Rest]
24+
? F extends Input
25+
? Rest extends Array<Input | IgnoredInput>
26+
? Merged<MergeObjects<S, F>, Rest>
27+
: MergeObjects<S, F>
28+
: F extends IgnoredInput
29+
? Rest extends Array<Input | IgnoredInput>
30+
? Merged<S, Rest>
31+
: S
32+
: S
33+
: S;
34+
35+
export type MergeFn = <Source extends Input, Defaults extends Array<Input | IgnoredInput>>(source: Source, ...defaults: Defaults) => Merged<Source, Defaults>;
36+
37+
export interface Instance extends MergeFn {
38+
// fn: MergeFn;
39+
// arrayFn: MergeFn;
40+
create: (merger?: Merger) => MergeFn;
41+
}
42+
43+
export type MergeArrays<Destination, Source> =
44+
Destination extends Array<infer DestinationType>
45+
? Source extends Array<infer SourceType>
46+
? Array<DestinationType | SourceType>
47+
: Source | Array<DestinationType>
48+
: Source | Destination;
49+
50+
export type Merge<Destination extends Input, Defaults extends Input> =
51+
// Remove explicitly null types
52+
Destination extends nullish
53+
? Defaults extends nullish
54+
? nullish
55+
: Defaults
56+
: Defaults extends nullish
57+
? Destination
58+
: // Handle arrays
59+
Destination extends Array<any>
60+
? Defaults extends Array<any>
61+
? MergeArrays<Destination, Defaults>
62+
: Destination | Defaults
63+
: // Don't attempt to merge Functions, RegExps, Promises
64+
// eslint-disable-next-line @typescript-eslint/ban-types
65+
Destination extends (...args: any) => any
66+
? Destination | Defaults
67+
: Destination extends RegExp
68+
? Destination | Defaults
69+
: Destination extends Promise<any>
70+
? Destination | Defaults
71+
: // Don't attempt to merge Functions, RegExps, Promises
72+
// eslint-disable-next-line @typescript-eslint/ban-types
73+
Defaults extends (...args: any) => any
74+
? Destination | Defaults
75+
: Defaults extends RegExp
76+
? Destination | Defaults
77+
: Defaults extends Promise<any>
78+
? Destination | Defaults
79+
: // Ensure we only merge Records
80+
Destination extends Input
81+
? Defaults extends Input
82+
? MergeObjects<Destination, Defaults>
83+
: Destination | Defaults
84+
: Destination | Defaults;
85+
}

nodekit/src/merge-config/utils.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Forked from sindresorhus/is-plain-obj (MIT)
2+
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
3+
export function isPlainObject(value: unknown): boolean {
4+
if (value === null || typeof value !== "object") {
5+
return false;
6+
}
7+
const prototype = Object.getPrototypeOf(value);
8+
9+
if (
10+
prototype !== null &&
11+
prototype !== Object.prototype &&
12+
Object.getPrototypeOf(prototype) !== null
13+
) {
14+
return false;
15+
}
16+
17+
if (Symbol.iterator in value) {
18+
return false;
19+
}
20+
21+
if (Symbol.toStringTag in value) {
22+
return Object.prototype.toString.call(value) === "[object Module]";
23+
}
24+
25+
return true;
26+
}

0 commit comments

Comments
 (0)