Buckets:
ktongue/docker_container / CAD_kevin /frontend /node_modules /webpack-dev-server /bin /process-arguments.js
| ; | |
| const path = require("path"); | |
| // Based on https://github.com/webpack/webpack/blob/master/lib/cli.js | |
| // Please do not modify it | |
| /** @typedef {"unknown-argument" | "unexpected-non-array-in-path" | "unexpected-non-object-in-path" | "multiple-values-unexpected" | "invalid-value"} ProblemType */ | |
| /** | |
| * @typedef {Object} Problem | |
| * @property {ProblemType} type | |
| * @property {string} path | |
| * @property {string} argument | |
| * @property {any=} value | |
| * @property {number=} index | |
| * @property {string=} expected | |
| */ | |
| /** | |
| * @typedef {Object} LocalProblem | |
| * @property {ProblemType} type | |
| * @property {string} path | |
| * @property {string=} expected | |
| */ | |
| /** | |
| * @typedef {Object} ArgumentConfig | |
| * @property {string} description | |
| * @property {string} path | |
| * @property {boolean} multiple | |
| * @property {"enum"|"string"|"path"|"number"|"boolean"|"RegExp"|"reset"} type | |
| * @property {any[]=} values | |
| */ | |
| /** | |
| * @typedef {Object} Argument | |
| * @property {string} description | |
| * @property {"string"|"number"|"boolean"} simpleType | |
| * @property {boolean} multiple | |
| * @property {ArgumentConfig[]} configs | |
| */ | |
| const cliAddedItems = new WeakMap(); | |
| /** | |
| * @param {any} config configuration | |
| * @param {string} schemaPath path in the config | |
| * @param {number | undefined} index index of value when multiple values are provided, otherwise undefined | |
| * @returns {{ problem?: LocalProblem, object?: any, property?: string | number, value?: any }} problem or object with property and value | |
| */ | |
| const getObjectAndProperty = (config, schemaPath, index = 0) => { | |
| if (!schemaPath) { | |
| return { value: config }; | |
| } | |
| const parts = schemaPath.split("."); | |
| const property = parts.pop(); | |
| let current = config; | |
| let i = 0; | |
| for (const part of parts) { | |
| const isArray = part.endsWith("[]"); | |
| const name = isArray ? part.slice(0, -2) : part; | |
| let value = current[name]; | |
| if (isArray) { | |
| // eslint-disable-next-line no-undefined | |
| if (value === undefined) { | |
| value = {}; | |
| current[name] = [...Array.from({ length: index }), value]; | |
| cliAddedItems.set(current[name], index + 1); | |
| } else if (!Array.isArray(value)) { | |
| return { | |
| problem: { | |
| type: "unexpected-non-array-in-path", | |
| path: parts.slice(0, i).join("."), | |
| }, | |
| }; | |
| } else { | |
| let addedItems = cliAddedItems.get(value) || 0; | |
| while (addedItems <= index) { | |
| // eslint-disable-next-line no-undefined | |
| value.push(undefined); | |
| // eslint-disable-next-line no-plusplus | |
| addedItems++; | |
| } | |
| cliAddedItems.set(value, addedItems); | |
| const x = value.length - addedItems + index; | |
| // eslint-disable-next-line no-undefined | |
| if (value[x] === undefined) { | |
| value[x] = {}; | |
| } else if (value[x] === null || typeof value[x] !== "object") { | |
| return { | |
| problem: { | |
| type: "unexpected-non-object-in-path", | |
| path: parts.slice(0, i).join("."), | |
| }, | |
| }; | |
| } | |
| value = value[x]; | |
| } | |
| // eslint-disable-next-line no-undefined | |
| } else if (value === undefined) { | |
| // eslint-disable-next-line no-multi-assign | |
| value = current[name] = {}; | |
| } else if (value === null || typeof value !== "object") { | |
| return { | |
| problem: { | |
| type: "unexpected-non-object-in-path", | |
| path: parts.slice(0, i).join("."), | |
| }, | |
| }; | |
| } | |
| current = value; | |
| // eslint-disable-next-line no-plusplus | |
| i++; | |
| } | |
| const value = current[/** @type {string} */ (property)]; | |
| if (/** @type {string} */ (property).endsWith("[]")) { | |
| const name = /** @type {string} */ (property).slice(0, -2); | |
| // eslint-disable-next-line no-shadow | |
| const value = current[name]; | |
| // eslint-disable-next-line no-undefined | |
| if (value === undefined) { | |
| // eslint-disable-next-line no-undefined | |
| current[name] = [...Array.from({ length: index }), undefined]; | |
| cliAddedItems.set(current[name], index + 1); | |
| // eslint-disable-next-line no-undefined | |
| return { object: current[name], property: index, value: undefined }; | |
| } else if (!Array.isArray(value)) { | |
| // eslint-disable-next-line no-undefined | |
| current[name] = [value, ...Array.from({ length: index }), undefined]; | |
| cliAddedItems.set(current[name], index + 1); | |
| // eslint-disable-next-line no-undefined | |
| return { object: current[name], property: index + 1, value: undefined }; | |
| } | |
| let addedItems = cliAddedItems.get(value) || 0; | |
| while (addedItems <= index) { | |
| // eslint-disable-next-line no-undefined | |
| value.push(undefined); | |
| // eslint-disable-next-line no-plusplus | |
| addedItems++; | |
| } | |
| cliAddedItems.set(value, addedItems); | |
| const x = value.length - addedItems + index; | |
| // eslint-disable-next-line no-undefined | |
| if (value[x] === undefined) { | |
| value[x] = {}; | |
| } else if (value[x] === null || typeof value[x] !== "object") { | |
| return { | |
| problem: { | |
| type: "unexpected-non-object-in-path", | |
| path: schemaPath, | |
| }, | |
| }; | |
| } | |
| return { | |
| object: value, | |
| property: x, | |
| value: value[x], | |
| }; | |
| } | |
| return { object: current, property, value }; | |
| }; | |
| /** | |
| * @param {ArgumentConfig} argConfig processing instructions | |
| * @param {any} value the value | |
| * @returns {any | undefined} parsed value | |
| */ | |
| const parseValueForArgumentConfig = (argConfig, value) => { | |
| // eslint-disable-next-line default-case | |
| switch (argConfig.type) { | |
| case "string": | |
| if (typeof value === "string") { | |
| return value; | |
| } | |
| break; | |
| case "path": | |
| if (typeof value === "string") { | |
| return path.resolve(value); | |
| } | |
| break; | |
| case "number": | |
| if (typeof value === "number") { | |
| return value; | |
| } | |
| if (typeof value === "string" && /^[+-]?\d*(\.\d*)[eE]\d+$/) { | |
| const n = +value; | |
| if (!isNaN(n)) return n; | |
| } | |
| break; | |
| case "boolean": | |
| if (typeof value === "boolean") { | |
| return value; | |
| } | |
| if (value === "true") { | |
| return true; | |
| } | |
| if (value === "false") { | |
| return false; | |
| } | |
| break; | |
| case "RegExp": | |
| if (value instanceof RegExp) { | |
| return value; | |
| } | |
| if (typeof value === "string") { | |
| // cspell:word yugi | |
| const match = /^\/(.*)\/([yugi]*)$/.exec(value); | |
| if (match && !/[^\\]\//.test(match[1])) { | |
| return new RegExp(match[1], match[2]); | |
| } | |
| } | |
| break; | |
| case "enum": | |
| if (/** @type {any[]} */ (argConfig.values).includes(value)) { | |
| return value; | |
| } | |
| for (const item of /** @type {any[]} */ (argConfig.values)) { | |
| if (`${item}` === value) return item; | |
| } | |
| break; | |
| case "reset": | |
| if (value === true) { | |
| return []; | |
| } | |
| break; | |
| } | |
| }; | |
| /** | |
| * @param {ArgumentConfig} argConfig processing instructions | |
| * @returns {string | undefined} expected message | |
| */ | |
| const getExpectedValue = (argConfig) => { | |
| switch (argConfig.type) { | |
| default: | |
| return argConfig.type; | |
| case "boolean": | |
| return "true | false"; | |
| case "RegExp": | |
| return "regular expression (example: /ab?c*/)"; | |
| case "enum": | |
| return /** @type {any[]} */ (argConfig.values) | |
| .map((v) => `${v}`) | |
| .join(" | "); | |
| case "reset": | |
| return "true (will reset the previous value to an empty array)"; | |
| } | |
| }; | |
| /** | |
| * @param {any} config configuration | |
| * @param {string} schemaPath path in the config | |
| * @param {any} value parsed value | |
| * @param {number | undefined} index index of value when multiple values are provided, otherwise undefined | |
| * @returns {LocalProblem | null} problem or null for success | |
| */ | |
| const setValue = (config, schemaPath, value, index) => { | |
| const { problem, object, property } = getObjectAndProperty( | |
| config, | |
| schemaPath, | |
| index | |
| ); | |
| if (problem) { | |
| return problem; | |
| } | |
| object[/** @type {string} */ (property)] = value; | |
| return null; | |
| }; | |
| /** | |
| * @param {ArgumentConfig} argConfig processing instructions | |
| * @param {any} config configuration | |
| * @param {any} value the value | |
| * @param {number | undefined} index the index if multiple values provided | |
| * @returns {LocalProblem | null} a problem if any | |
| */ | |
| const processArgumentConfig = (argConfig, config, value, index) => { | |
| // eslint-disable-next-line no-undefined | |
| if (index !== undefined && !argConfig.multiple) { | |
| return { | |
| type: "multiple-values-unexpected", | |
| path: argConfig.path, | |
| }; | |
| } | |
| const parsed = parseValueForArgumentConfig(argConfig, value); | |
| // eslint-disable-next-line no-undefined | |
| if (parsed === undefined) { | |
| return { | |
| type: "invalid-value", | |
| path: argConfig.path, | |
| expected: getExpectedValue(argConfig), | |
| }; | |
| } | |
| const problem = setValue(config, argConfig.path, parsed, index); | |
| if (problem) { | |
| return problem; | |
| } | |
| return null; | |
| }; | |
| /** | |
| * @param {Record<string, Argument>} args object of arguments | |
| * @param {any} config configuration | |
| * @param {Record<string, string | number | boolean | RegExp | (string | number | boolean | RegExp)[]>} values object with values | |
| * @returns {Problem[] | null} problems or null for success | |
| */ | |
| const processArguments = (args, config, values) => { | |
| /** | |
| * @type {Problem[]} | |
| */ | |
| const problems = []; | |
| for (const key of Object.keys(values)) { | |
| const arg = args[key]; | |
| if (!arg) { | |
| problems.push({ | |
| type: "unknown-argument", | |
| path: "", | |
| argument: key, | |
| }); | |
| // eslint-disable-next-line no-continue | |
| continue; | |
| } | |
| /** | |
| * @param {any} value | |
| * @param {number | undefined} i | |
| */ | |
| const processValue = (value, i) => { | |
| const currentProblems = []; | |
| for (const argConfig of arg.configs) { | |
| const problem = processArgumentConfig(argConfig, config, value, i); | |
| if (!problem) { | |
| return; | |
| } | |
| currentProblems.push({ | |
| ...problem, | |
| argument: key, | |
| value, | |
| index: i, | |
| }); | |
| } | |
| problems.push(...currentProblems); | |
| }; | |
| const value = values[key]; | |
| if (Array.isArray(value)) { | |
| for (let i = 0; i < value.length; i++) { | |
| processValue(value[i], i); | |
| } | |
| } else { | |
| // eslint-disable-next-line no-undefined | |
| processValue(value, undefined); | |
| } | |
| } | |
| if (problems.length === 0) { | |
| return null; | |
| } | |
| return problems; | |
| }; | |
| module.exports = processArguments; | |
Xet Storage Details
- Size:
- 10.6 kB
- Xet hash:
- 6d1c49201944fe3ed1cf678afeaa4515541ba0c1e1db8be19a5879cadc20320b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.