啊鑫
2025-07-17 eaa506e57403d1b8502f16ca5dd6e82c347724d0
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
95
96
97
98
99
100
101
102
103
104
105
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
 
"use strict";
 
/**
 * @template T
 * @typedef {Record<string, string | string[] | T>} Item
 */
 
/**
 * @template T
 * @typedef {(string | Item<T>)[] | Item<T>} ContainerOptionsFormat
 */
 
/**
 * @template T
 * @template N
 * @param {ContainerOptionsFormat<T>} options options passed by the user
 * @param {(item: string | string[], itemOrKey: string) => N} normalizeSimple normalize a simple item
 * @param {(value: T, key: string) => N} normalizeOptions normalize a complex item
 * @param {(item: string, normalized: N) => void} fn processing function
 * @returns {void}
 */
const process = (options, normalizeSimple, normalizeOptions, fn) => {
    /**
     * @param {(string | Item<T>)[]} items items
     */
    const array = items => {
        for (const item of items) {
            if (typeof item === "string") {
                fn(item, normalizeSimple(item, item));
            } else if (item && typeof item === "object") {
                object(item);
            } else {
                throw new Error("Unexpected options format");
            }
        }
    };
    /**
     * @param {Item<T>} obj an object
     */
    const object = obj => {
        for (const [key, value] of Object.entries(obj)) {
            if (typeof value === "string" || Array.isArray(value)) {
                fn(key, normalizeSimple(value, key));
            } else {
                fn(key, normalizeOptions(value, key));
            }
        }
    };
    if (!options) {
        // Do nothing
    } else if (Array.isArray(options)) {
        array(options);
    } else if (typeof options === "object") {
        object(options);
    } else {
        throw new Error("Unexpected options format");
    }
};
 
/**
 * @template T
 * @template R
 * @param {ContainerOptionsFormat<T>} options options passed by the user
 * @param {(item: string | string[], itemOrKey: string) => R} normalizeSimple normalize a simple item
 * @param {(value: T, key: string) => R} normalizeOptions normalize a complex item
 * @returns {[string, R][]} parsed options
 */
const parseOptions = (options, normalizeSimple, normalizeOptions) => {
    /** @type {[string, R][]} */
    const items = [];
    process(options, normalizeSimple, normalizeOptions, (key, value) => {
        items.push([key, value]);
    });
    return items;
};
 
/**
 * @template T
 * @param {string} scope scope name
 * @param {ContainerOptionsFormat<T>} options options passed by the user
 * @returns {Record<string, string | string[] | T>} options to spread or pass
 */
const scope = (scope, options) => {
    /** @type {Record<string, string | string[] | T>} */
    const obj = {};
    process(
        options,
        item => /** @type {string | string[] | T} */ (item),
        item => /** @type {string | string[] | T} */ (item),
        (key, value) => {
            obj[
                key.startsWith("./") ? `${scope}${key.slice(1)}` : `${scope}/${key}`
            ] = value;
        }
    );
    return obj;
};
 
module.exports.parseOptions = parseOptions;
module.exports.scope = scope;