ogi-addon 2.4.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,7 +25,7 @@ function isActionOption(option) {
25
25
  * A builder for creating configuration screens. The generic type T accumulates
26
26
  * the types of all options added to the builder, enabling type-safe access to
27
27
  * the configuration values.
28
- *
28
+ *
29
29
  * @template T - The accumulated type of all configuration options
30
30
  */
31
31
  var ConfigurationBuilder = class {
@@ -61,7 +61,7 @@ var ConfigurationBuilder = class {
61
61
  return this;
62
62
  }
63
63
  /**
64
- * Add an action option to the configuration builder and return the builder for chaining.
64
+ * Add an action option to the configuration builder and return the builder for chaining.
65
65
  * Action options contribute a boolean to the return type (true if clicked, false if not).
66
66
  * You must provide a name, display name, and description for the option.
67
67
  * @param option { (option: ActionOption) => ActionOption<K> }
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigurationBuilder.cjs","names":["z","ZodError"],"sources":["../../src/config/ConfigurationBuilder.ts"],"sourcesContent":["import z, { ZodError } from 'zod';\n\nexport interface ConfigurationFile {\n [key: string]: ConfigurationOption<string>;\n}\n\nconst configValidation = z.object({\n name: z.string().min(1),\n displayName: z.string().min(1),\n description: z.string().min(1),\n});\n\nexport function isStringOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is StringOption<N> {\n return option.type === 'string';\n}\n\nexport function isNumberOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is NumberOption<N> {\n return option.type === 'number';\n}\n\nexport function isBooleanOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is BooleanOption<N> {\n return option.type === 'boolean';\n}\n\nexport function isActionOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is ActionOption<N> {\n return option.type === 'action';\n}\n\n/**\n * A builder for creating configuration screens. The generic type T accumulates\n * the types of all options added to the builder, enabling type-safe access to\n * the configuration values.\n * \n * @template T - The accumulated type of all configuration options\n */\nexport class ConfigurationBuilder<\n T extends Record<string, string | number | boolean> = {}\n> {\n private options: ConfigurationOption<string>[] = [];\n\n /**\n * Add a number option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: NumberOption) => NumberOption<K> }\n * @returns A new ConfigurationBuilder with the number option's type added\n */\n public addNumberOption<K extends string>(\n option: (option: NumberOption) => NumberOption<K>\n ): ConfigurationBuilder<T & { [P in K]: number }> {\n let newOption = new NumberOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: number }>;\n }\n\n /**\n * Add a string option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: StringOption) => StringOption<K> }\n * @returns A new ConfigurationBuilder with the string option's type added\n */\n public addStringOption<K extends string>(\n option: (option: StringOption) => StringOption<K>\n ): ConfigurationBuilder<T & { [P in K]: string }> {\n let newOption = new StringOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: string }>;\n }\n\n /**\n * Add a boolean option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: BooleanOption) => BooleanOption<K> }\n * @returns A new ConfigurationBuilder with the boolean option's type added\n */\n public addBooleanOption<K extends string>(\n option: (option: BooleanOption) => BooleanOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new BooleanOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n /**\n * Add an action option to the configuration builder and return the builder for chaining. \n * Action options contribute a boolean to the return type (true if clicked, false if not).\n * You must provide a name, display name, and description for the option.\n * @param option { (option: ActionOption) => ActionOption<K> }\n * @returns A new ConfigurationBuilder with the action option's type added as boolean\n */\n public addActionOption<K extends string>(\n option: (option: ActionOption) => ActionOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new ActionOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n public build(includeFunctions: boolean): ConfigurationFile {\n let config: ConfigurationFile = {};\n this.options.forEach((option) => {\n // remove all functions from the option object\n if (!includeFunctions) {\n option = JSON.parse(JSON.stringify(option));\n const optionData = configValidation.safeParse(option);\n if (!optionData.success) {\n throw new ZodError(optionData.error.errors);\n }\n\n config[option.name] = option;\n } else {\n config[option.name] = option;\n }\n });\n return config;\n }\n}\n\nexport type ConfigurationOptionType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'action'\n | 'unset';\nexport class ConfigurationOption<N extends string = string> {\n public name: N = '' as N;\n public defaultValue: unknown = '';\n public displayName: string = '';\n public description: string = '';\n public type: ConfigurationOptionType = 'unset';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n setName<K extends string>(name: K): ConfigurationOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ConfigurationOption<K>;\n }\n\n /**\n * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**\n * @param displayName {string} The display name of the option.\n * @returns\n */\n setDisplayName(displayName: string): this {\n this.displayName = displayName;\n return this;\n }\n\n /**\n * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**\n * @param description {string} The description of the option.\n * @returns\n */\n setDescription(description: string): this {\n this.description = description;\n return this;\n }\n\n /**\n * Validation code for the option. This is called when the user provides input to the option. If the validation fails, the user will be prompted to provide input again.\n * @param input {unknown} The input to validate\n */\n validate(input: unknown): [boolean, string] {\n throw new Error('Validation code not implemented. Value: ' + input);\n }\n}\n\nexport class StringOption<N extends string = string> extends ConfigurationOption<N> {\n public allowedValues: string[] = [];\n public minTextLength: number = 0;\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: string = '';\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\n public type: ConfigurationOptionType = 'string';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): StringOption<K> {\n this.name = name as unknown as N;\n return this as unknown as StringOption<K>;\n }\n\n /**\n * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.\n * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.\n */\n setAllowedValues(allowedValues: string[]): this {\n this.allowedValues = allowedValues;\n return this;\n }\n\n /**\n * Set the default value for the string. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {string} The default value for the string.\n */\n setDefaultValue(defaultValue: string): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n /**\n * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.\n * @param minTextLength {number} The minimum text length for the string.\n */\n setMinTextLength(minTextLength: number): this {\n this.minTextLength = minTextLength;\n return this;\n }\n\n /**\n * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.\n * @param maxTextLength {number} The maximum text length for the string.\n */\n setMaxTextLength(maxTextLength: number): this {\n this.maxTextLength = maxTextLength;\n return this;\n }\n\n /**\n * Set the input type for the string. This will change how the client renders the input.\n * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.\n */\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\n this.inputType = inputType;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'string') {\n return [false, 'Input is not a string'];\n }\n if (this.allowedValues.length === 0 && input.length !== 0)\n return [true, ''];\n if (\n input.length < this.minTextLength ||\n input.length > this.maxTextLength\n ) {\n return [\n false,\n 'Input is not within the text length ' +\n this.minTextLength +\n ' and ' +\n this.maxTextLength +\n ' characters (currently ' +\n input.length +\n ' characters)',\n ];\n }\n\n return [\n this.allowedValues.includes(input),\n 'Input is not an allowed value',\n ];\n }\n}\n\nexport class NumberOption<N extends string = string> extends ConfigurationOption<N> {\n public min: number = 0;\n public max: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: number = 0;\n public type: ConfigurationOptionType = 'number';\n public inputType: 'range' | 'number' = 'number';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): NumberOption<K> {\n this.name = name as unknown as N;\n return this as unknown as NumberOption<K>;\n }\n\n /**\n * Set the minimum value for the number. If the user provides a number that is less than this value, the validation will fail.\n * @param min {number} The minimum value for the number.\n */\n setMin(min: number): this {\n this.min = min;\n return this;\n }\n\n /**\n * Set the input type for the number. This will change how the client renders the input.\n * @param type {'range' | 'number'} The input type for the number.\n */\n setInputType(type: 'range' | 'number'): this {\n this.inputType = type;\n return this;\n }\n\n /**\n * Set the maximum value for the number. If the user provides a number that is greater than this value, the validation will fail.\n * @param max {number} The maximum value for the number.\n */\n setMax(max: number): this {\n this.max = max;\n return this;\n }\n\n /**\n * Set the default value for the number. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {number} The default value for the number.\n */\n setDefaultValue(defaultValue: number): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (isNaN(Number(input))) {\n return [false, 'Input is not a number'];\n }\n if (Number(input) < this.min || Number(input) > this.max) {\n return [\n false,\n 'Input is not within the range of ' + this.min + ' and ' + this.max,\n ];\n }\n return [true, ''];\n }\n}\n\nexport class BooleanOption<N extends string = string> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'boolean';\n public defaultValue: boolean = false;\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): BooleanOption<K> {\n this.name = name as unknown as N;\n return this as unknown as BooleanOption<K>;\n }\n\n /**\n * Set the default value for the boolean. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {boolean} The default value for the boolean.\n */\n setDefaultValue(defaultValue: boolean): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'boolean') {\n return [false, 'Input is not a boolean'];\n }\n return [true, ''];\n }\n}\n\nexport class ActionOption<N extends string = string> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'action';\n public manifest: Record<string, unknown> = {};\n public buttonText: string = 'Run';\n public taskName: string = '';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): ActionOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ActionOption<K>;\n }\n\n /**\n * Set the task name that will be used to identify which task handler to run. This should match the name used in `addon.onTask()`.\n * @param taskName {string} The task name to identify the handler.\n */\n setTaskName(taskName: string): this {\n this.taskName = taskName;\n return this;\n }\n\n /**\n * Set the manifest object that will be passed to the task-run handler. The task name should be set via setTaskName() rather than in the manifest.\n * @param manifest {Record<string, unknown>} The manifest object to pass to the task handler.\n */\n setManifest(manifest: Record<string, unknown>): this {\n this.manifest = manifest;\n return this;\n }\n\n /**\n * Set the text displayed on the action button.\n * @param text {string} The button text.\n */\n setButtonText(text: string): this {\n this.buttonText = text;\n return this;\n }\n\n override validate(_input: unknown): [boolean, string] {\n return [true, ''];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigurationBuilder.cjs","names":["z","ZodError"],"sources":["../../src/config/ConfigurationBuilder.ts"],"sourcesContent":["import z, { ZodError } from 'zod';\n\nexport interface ConfigurationFile {\n [key: string]: ConfigurationOption<string>;\n}\n\nconst configValidation = z.object({\n name: z.string().min(1),\n displayName: z.string().min(1),\n description: z.string().min(1),\n});\n\nexport function isStringOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is StringOption<N> {\n return option.type === 'string';\n}\n\nexport function isNumberOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is NumberOption<N> {\n return option.type === 'number';\n}\n\nexport function isBooleanOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is BooleanOption<N> {\n return option.type === 'boolean';\n}\n\nexport function isActionOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is ActionOption<N> {\n return option.type === 'action';\n}\n\n/**\n * A builder for creating configuration screens. The generic type T accumulates\n * the types of all options added to the builder, enabling type-safe access to\n * the configuration values.\n *\n * @template T - The accumulated type of all configuration options\n */\nexport class ConfigurationBuilder<\n T extends Record<string, string | number | boolean> = {},\n> {\n private options: ConfigurationOption<string>[] = [];\n\n /**\n * Add a number option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: NumberOption) => NumberOption<K> }\n * @returns A new ConfigurationBuilder with the number option's type added\n */\n public addNumberOption<K extends string>(\n option: (option: NumberOption) => NumberOption<K>\n ): ConfigurationBuilder<T & { [P in K]: number }> {\n let newOption = new NumberOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: number }>;\n }\n\n /**\n * Add a string option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: StringOption) => StringOption<K> }\n * @returns A new ConfigurationBuilder with the string option's type added\n */\n public addStringOption<K extends string>(\n option: (option: StringOption) => StringOption<K>\n ): ConfigurationBuilder<T & { [P in K]: string }> {\n let newOption = new StringOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: string }>;\n }\n\n /**\n * Add a boolean option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: BooleanOption) => BooleanOption<K> }\n * @returns A new ConfigurationBuilder with the boolean option's type added\n */\n public addBooleanOption<K extends string>(\n option: (option: BooleanOption) => BooleanOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new BooleanOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n /**\n * Add an action option to the configuration builder and return the builder for chaining.\n * Action options contribute a boolean to the return type (true if clicked, false if not).\n * You must provide a name, display name, and description for the option.\n * @param option { (option: ActionOption) => ActionOption<K> }\n * @returns A new ConfigurationBuilder with the action option's type added as boolean\n */\n public addActionOption<K extends string>(\n option: (option: ActionOption) => ActionOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new ActionOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n public build(includeFunctions: boolean): ConfigurationFile {\n let config: ConfigurationFile = {};\n this.options.forEach((option) => {\n // remove all functions from the option object\n if (!includeFunctions) {\n option = JSON.parse(JSON.stringify(option));\n const optionData = configValidation.safeParse(option);\n if (!optionData.success) {\n throw new ZodError(optionData.error.errors);\n }\n\n config[option.name] = option;\n } else {\n config[option.name] = option;\n }\n });\n return config;\n }\n}\n\nexport type ConfigurationOptionType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'action'\n | 'unset';\nexport class ConfigurationOption<N extends string = string> {\n public name: N = '' as N;\n public defaultValue: unknown = '';\n public displayName: string = '';\n public description: string = '';\n public type: ConfigurationOptionType = 'unset';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n setName<K extends string>(name: K): ConfigurationOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ConfigurationOption<K>;\n }\n\n /**\n * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**\n * @param displayName {string} The display name of the option.\n * @returns\n */\n setDisplayName(displayName: string): this {\n this.displayName = displayName;\n return this;\n }\n\n /**\n * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**\n * @param description {string} The description of the option.\n * @returns\n */\n setDescription(description: string): this {\n this.description = description;\n return this;\n }\n\n /**\n * Validation code for the option. This is called when the user provides input to the option. If the validation fails, the user will be prompted to provide input again.\n * @param input {unknown} The input to validate\n */\n validate(input: unknown): [boolean, string] {\n throw new Error('Validation code not implemented. Value: ' + input);\n }\n}\n\nexport class StringOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public allowedValues: string[] = [];\n public minTextLength: number = 0;\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: string = '';\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\n public type: ConfigurationOptionType = 'string';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): StringOption<K> {\n this.name = name as unknown as N;\n return this as unknown as StringOption<K>;\n }\n\n /**\n * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.\n * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.\n */\n setAllowedValues(allowedValues: string[]): this {\n this.allowedValues = allowedValues;\n return this;\n }\n\n /**\n * Set the default value for the string. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {string} The default value for the string.\n */\n setDefaultValue(defaultValue: string): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n /**\n * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.\n * @param minTextLength {number} The minimum text length for the string.\n */\n setMinTextLength(minTextLength: number): this {\n this.minTextLength = minTextLength;\n return this;\n }\n\n /**\n * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.\n * @param maxTextLength {number} The maximum text length for the string.\n */\n setMaxTextLength(maxTextLength: number): this {\n this.maxTextLength = maxTextLength;\n return this;\n }\n\n /**\n * Set the input type for the string. This will change how the client renders the input.\n * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.\n */\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\n this.inputType = inputType;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'string') {\n return [false, 'Input is not a string'];\n }\n if (this.allowedValues.length === 0 && input.length !== 0)\n return [true, ''];\n if (\n input.length < this.minTextLength ||\n input.length > this.maxTextLength\n ) {\n return [\n false,\n 'Input is not within the text length ' +\n this.minTextLength +\n ' and ' +\n this.maxTextLength +\n ' characters (currently ' +\n input.length +\n ' characters)',\n ];\n }\n\n return [\n this.allowedValues.includes(input),\n 'Input is not an allowed value',\n ];\n }\n}\n\nexport class NumberOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public min: number = 0;\n public max: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: number = 0;\n public type: ConfigurationOptionType = 'number';\n public inputType: 'range' | 'number' = 'number';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): NumberOption<K> {\n this.name = name as unknown as N;\n return this as unknown as NumberOption<K>;\n }\n\n /**\n * Set the minimum value for the number. If the user provides a number that is less than this value, the validation will fail.\n * @param min {number} The minimum value for the number.\n */\n setMin(min: number): this {\n this.min = min;\n return this;\n }\n\n /**\n * Set the input type for the number. This will change how the client renders the input.\n * @param type {'range' | 'number'} The input type for the number.\n */\n setInputType(type: 'range' | 'number'): this {\n this.inputType = type;\n return this;\n }\n\n /**\n * Set the maximum value for the number. If the user provides a number that is greater than this value, the validation will fail.\n * @param max {number} The maximum value for the number.\n */\n setMax(max: number): this {\n this.max = max;\n return this;\n }\n\n /**\n * Set the default value for the number. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {number} The default value for the number.\n */\n setDefaultValue(defaultValue: number): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (isNaN(Number(input))) {\n return [false, 'Input is not a number'];\n }\n if (Number(input) < this.min || Number(input) > this.max) {\n return [\n false,\n 'Input is not within the range of ' + this.min + ' and ' + this.max,\n ];\n }\n return [true, ''];\n }\n}\n\nexport class BooleanOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'boolean';\n public defaultValue: boolean = false;\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): BooleanOption<K> {\n this.name = name as unknown as N;\n return this as unknown as BooleanOption<K>;\n }\n\n /**\n * Set the default value for the boolean. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {boolean} The default value for the boolean.\n */\n setDefaultValue(defaultValue: boolean): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'boolean') {\n return [false, 'Input is not a boolean'];\n }\n return [true, ''];\n }\n}\n\nexport class ActionOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'action';\n public manifest: Record<string, unknown> = {};\n public buttonText: string = 'Run';\n public taskName: string = '';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): ActionOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ActionOption<K>;\n }\n\n /**\n * Set the task name that will be used to identify which task handler to run. This should match the name used in `addon.onTask()`.\n * @param taskName {string} The task name to identify the handler.\n */\n setTaskName(taskName: string): this {\n this.taskName = taskName;\n return this;\n }\n\n /**\n * Set the manifest object that will be passed to the task-run handler. The task name should be set via setTaskName() rather than in the manifest.\n * @param manifest {Record<string, unknown>} The manifest object to pass to the task handler.\n */\n setManifest(manifest: Record<string, unknown>): this {\n this.manifest = manifest;\n return this;\n }\n\n /**\n * Set the text displayed on the action button.\n * @param text {string} The button text.\n */\n setButtonText(text: string): this {\n this.buttonText = text;\n return this;\n }\n\n override validate(_input: unknown): [boolean, string] {\n return [true, ''];\n }\n}\n"],"mappings":"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"}
@@ -22,7 +22,7 @@ function isActionOption(option) {
22
22
  * A builder for creating configuration screens. The generic type T accumulates
23
23
  * the types of all options added to the builder, enabling type-safe access to
24
24
  * the configuration values.
25
- *
25
+ *
26
26
  * @template T - The accumulated type of all configuration options
27
27
  */
28
28
  var ConfigurationBuilder = class {
@@ -58,7 +58,7 @@ var ConfigurationBuilder = class {
58
58
  return this;
59
59
  }
60
60
  /**
61
- * Add an action option to the configuration builder and return the builder for chaining.
61
+ * Add an action option to the configuration builder and return the builder for chaining.
62
62
  * Action options contribute a boolean to the return type (true if clicked, false if not).
63
63
  * You must provide a name, display name, and description for the option.
64
64
  * @param option { (option: ActionOption) => ActionOption<K> }
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigurationBuilder.mjs","names":[],"sources":["../../src/config/ConfigurationBuilder.ts"],"sourcesContent":["import z, { ZodError } from 'zod';\n\nexport interface ConfigurationFile {\n [key: string]: ConfigurationOption<string>;\n}\n\nconst configValidation = z.object({\n name: z.string().min(1),\n displayName: z.string().min(1),\n description: z.string().min(1),\n});\n\nexport function isStringOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is StringOption<N> {\n return option.type === 'string';\n}\n\nexport function isNumberOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is NumberOption<N> {\n return option.type === 'number';\n}\n\nexport function isBooleanOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is BooleanOption<N> {\n return option.type === 'boolean';\n}\n\nexport function isActionOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is ActionOption<N> {\n return option.type === 'action';\n}\n\n/**\n * A builder for creating configuration screens. The generic type T accumulates\n * the types of all options added to the builder, enabling type-safe access to\n * the configuration values.\n * \n * @template T - The accumulated type of all configuration options\n */\nexport class ConfigurationBuilder<\n T extends Record<string, string | number | boolean> = {}\n> {\n private options: ConfigurationOption<string>[] = [];\n\n /**\n * Add a number option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: NumberOption) => NumberOption<K> }\n * @returns A new ConfigurationBuilder with the number option's type added\n */\n public addNumberOption<K extends string>(\n option: (option: NumberOption) => NumberOption<K>\n ): ConfigurationBuilder<T & { [P in K]: number }> {\n let newOption = new NumberOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: number }>;\n }\n\n /**\n * Add a string option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: StringOption) => StringOption<K> }\n * @returns A new ConfigurationBuilder with the string option's type added\n */\n public addStringOption<K extends string>(\n option: (option: StringOption) => StringOption<K>\n ): ConfigurationBuilder<T & { [P in K]: string }> {\n let newOption = new StringOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: string }>;\n }\n\n /**\n * Add a boolean option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: BooleanOption) => BooleanOption<K> }\n * @returns A new ConfigurationBuilder with the boolean option's type added\n */\n public addBooleanOption<K extends string>(\n option: (option: BooleanOption) => BooleanOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new BooleanOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n /**\n * Add an action option to the configuration builder and return the builder for chaining. \n * Action options contribute a boolean to the return type (true if clicked, false if not).\n * You must provide a name, display name, and description for the option.\n * @param option { (option: ActionOption) => ActionOption<K> }\n * @returns A new ConfigurationBuilder with the action option's type added as boolean\n */\n public addActionOption<K extends string>(\n option: (option: ActionOption) => ActionOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new ActionOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n public build(includeFunctions: boolean): ConfigurationFile {\n let config: ConfigurationFile = {};\n this.options.forEach((option) => {\n // remove all functions from the option object\n if (!includeFunctions) {\n option = JSON.parse(JSON.stringify(option));\n const optionData = configValidation.safeParse(option);\n if (!optionData.success) {\n throw new ZodError(optionData.error.errors);\n }\n\n config[option.name] = option;\n } else {\n config[option.name] = option;\n }\n });\n return config;\n }\n}\n\nexport type ConfigurationOptionType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'action'\n | 'unset';\nexport class ConfigurationOption<N extends string = string> {\n public name: N = '' as N;\n public defaultValue: unknown = '';\n public displayName: string = '';\n public description: string = '';\n public type: ConfigurationOptionType = 'unset';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n setName<K extends string>(name: K): ConfigurationOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ConfigurationOption<K>;\n }\n\n /**\n * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**\n * @param displayName {string} The display name of the option.\n * @returns\n */\n setDisplayName(displayName: string): this {\n this.displayName = displayName;\n return this;\n }\n\n /**\n * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**\n * @param description {string} The description of the option.\n * @returns\n */\n setDescription(description: string): this {\n this.description = description;\n return this;\n }\n\n /**\n * Validation code for the option. This is called when the user provides input to the option. If the validation fails, the user will be prompted to provide input again.\n * @param input {unknown} The input to validate\n */\n validate(input: unknown): [boolean, string] {\n throw new Error('Validation code not implemented. Value: ' + input);\n }\n}\n\nexport class StringOption<N extends string = string> extends ConfigurationOption<N> {\n public allowedValues: string[] = [];\n public minTextLength: number = 0;\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: string = '';\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\n public type: ConfigurationOptionType = 'string';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): StringOption<K> {\n this.name = name as unknown as N;\n return this as unknown as StringOption<K>;\n }\n\n /**\n * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.\n * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.\n */\n setAllowedValues(allowedValues: string[]): this {\n this.allowedValues = allowedValues;\n return this;\n }\n\n /**\n * Set the default value for the string. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {string} The default value for the string.\n */\n setDefaultValue(defaultValue: string): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n /**\n * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.\n * @param minTextLength {number} The minimum text length for the string.\n */\n setMinTextLength(minTextLength: number): this {\n this.minTextLength = minTextLength;\n return this;\n }\n\n /**\n * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.\n * @param maxTextLength {number} The maximum text length for the string.\n */\n setMaxTextLength(maxTextLength: number): this {\n this.maxTextLength = maxTextLength;\n return this;\n }\n\n /**\n * Set the input type for the string. This will change how the client renders the input.\n * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.\n */\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\n this.inputType = inputType;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'string') {\n return [false, 'Input is not a string'];\n }\n if (this.allowedValues.length === 0 && input.length !== 0)\n return [true, ''];\n if (\n input.length < this.minTextLength ||\n input.length > this.maxTextLength\n ) {\n return [\n false,\n 'Input is not within the text length ' +\n this.minTextLength +\n ' and ' +\n this.maxTextLength +\n ' characters (currently ' +\n input.length +\n ' characters)',\n ];\n }\n\n return [\n this.allowedValues.includes(input),\n 'Input is not an allowed value',\n ];\n }\n}\n\nexport class NumberOption<N extends string = string> extends ConfigurationOption<N> {\n public min: number = 0;\n public max: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: number = 0;\n public type: ConfigurationOptionType = 'number';\n public inputType: 'range' | 'number' = 'number';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): NumberOption<K> {\n this.name = name as unknown as N;\n return this as unknown as NumberOption<K>;\n }\n\n /**\n * Set the minimum value for the number. If the user provides a number that is less than this value, the validation will fail.\n * @param min {number} The minimum value for the number.\n */\n setMin(min: number): this {\n this.min = min;\n return this;\n }\n\n /**\n * Set the input type for the number. This will change how the client renders the input.\n * @param type {'range' | 'number'} The input type for the number.\n */\n setInputType(type: 'range' | 'number'): this {\n this.inputType = type;\n return this;\n }\n\n /**\n * Set the maximum value for the number. If the user provides a number that is greater than this value, the validation will fail.\n * @param max {number} The maximum value for the number.\n */\n setMax(max: number): this {\n this.max = max;\n return this;\n }\n\n /**\n * Set the default value for the number. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {number} The default value for the number.\n */\n setDefaultValue(defaultValue: number): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (isNaN(Number(input))) {\n return [false, 'Input is not a number'];\n }\n if (Number(input) < this.min || Number(input) > this.max) {\n return [\n false,\n 'Input is not within the range of ' + this.min + ' and ' + this.max,\n ];\n }\n return [true, ''];\n }\n}\n\nexport class BooleanOption<N extends string = string> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'boolean';\n public defaultValue: boolean = false;\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): BooleanOption<K> {\n this.name = name as unknown as N;\n return this as unknown as BooleanOption<K>;\n }\n\n /**\n * Set the default value for the boolean. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {boolean} The default value for the boolean.\n */\n setDefaultValue(defaultValue: boolean): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'boolean') {\n return [false, 'Input is not a boolean'];\n }\n return [true, ''];\n }\n}\n\nexport class ActionOption<N extends string = string> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'action';\n public manifest: Record<string, unknown> = {};\n public buttonText: string = 'Run';\n public taskName: string = '';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): ActionOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ActionOption<K>;\n }\n\n /**\n * Set the task name that will be used to identify which task handler to run. This should match the name used in `addon.onTask()`.\n * @param taskName {string} The task name to identify the handler.\n */\n setTaskName(taskName: string): this {\n this.taskName = taskName;\n return this;\n }\n\n /**\n * Set the manifest object that will be passed to the task-run handler. The task name should be set via setTaskName() rather than in the manifest.\n * @param manifest {Record<string, unknown>} The manifest object to pass to the task handler.\n */\n setManifest(manifest: Record<string, unknown>): this {\n this.manifest = manifest;\n return this;\n }\n\n /**\n * Set the text displayed on the action button.\n * @param text {string} The button text.\n */\n setButtonText(text: string): this {\n this.buttonText = text;\n return this;\n }\n\n override validate(_input: unknown): [boolean, string] {\n return [true, ''];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigurationBuilder.mjs","names":[],"sources":["../../src/config/ConfigurationBuilder.ts"],"sourcesContent":["import z, { ZodError } from 'zod';\n\nexport interface ConfigurationFile {\n [key: string]: ConfigurationOption<string>;\n}\n\nconst configValidation = z.object({\n name: z.string().min(1),\n displayName: z.string().min(1),\n description: z.string().min(1),\n});\n\nexport function isStringOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is StringOption<N> {\n return option.type === 'string';\n}\n\nexport function isNumberOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is NumberOption<N> {\n return option.type === 'number';\n}\n\nexport function isBooleanOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is BooleanOption<N> {\n return option.type === 'boolean';\n}\n\nexport function isActionOption<N extends string = string>(\n option: ConfigurationOption<N>\n): option is ActionOption<N> {\n return option.type === 'action';\n}\n\n/**\n * A builder for creating configuration screens. The generic type T accumulates\n * the types of all options added to the builder, enabling type-safe access to\n * the configuration values.\n *\n * @template T - The accumulated type of all configuration options\n */\nexport class ConfigurationBuilder<\n T extends Record<string, string | number | boolean> = {},\n> {\n private options: ConfigurationOption<string>[] = [];\n\n /**\n * Add a number option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: NumberOption) => NumberOption<K> }\n * @returns A new ConfigurationBuilder with the number option's type added\n */\n public addNumberOption<K extends string>(\n option: (option: NumberOption) => NumberOption<K>\n ): ConfigurationBuilder<T & { [P in K]: number }> {\n let newOption = new NumberOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: number }>;\n }\n\n /**\n * Add a string option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: StringOption) => StringOption<K> }\n * @returns A new ConfigurationBuilder with the string option's type added\n */\n public addStringOption<K extends string>(\n option: (option: StringOption) => StringOption<K>\n ): ConfigurationBuilder<T & { [P in K]: string }> {\n let newOption = new StringOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: string }>;\n }\n\n /**\n * Add a boolean option to the configuration builder and return the builder for chaining. You must provide a name, display name, and description for the option.\n * @param option { (option: BooleanOption) => BooleanOption<K> }\n * @returns A new ConfigurationBuilder with the boolean option's type added\n */\n public addBooleanOption<K extends string>(\n option: (option: BooleanOption) => BooleanOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new BooleanOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n /**\n * Add an action option to the configuration builder and return the builder for chaining.\n * Action options contribute a boolean to the return type (true if clicked, false if not).\n * You must provide a name, display name, and description for the option.\n * @param option { (option: ActionOption) => ActionOption<K> }\n * @returns A new ConfigurationBuilder with the action option's type added as boolean\n */\n public addActionOption<K extends string>(\n option: (option: ActionOption) => ActionOption<K>\n ): ConfigurationBuilder<T & { [P in K]: boolean }> {\n let newOption = new ActionOption();\n const configuredOption = option(newOption);\n this.options.push(configuredOption);\n return this as unknown as ConfigurationBuilder<T & { [P in K]: boolean }>;\n }\n\n public build(includeFunctions: boolean): ConfigurationFile {\n let config: ConfigurationFile = {};\n this.options.forEach((option) => {\n // remove all functions from the option object\n if (!includeFunctions) {\n option = JSON.parse(JSON.stringify(option));\n const optionData = configValidation.safeParse(option);\n if (!optionData.success) {\n throw new ZodError(optionData.error.errors);\n }\n\n config[option.name] = option;\n } else {\n config[option.name] = option;\n }\n });\n return config;\n }\n}\n\nexport type ConfigurationOptionType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'action'\n | 'unset';\nexport class ConfigurationOption<N extends string = string> {\n public name: N = '' as N;\n public defaultValue: unknown = '';\n public displayName: string = '';\n public description: string = '';\n public type: ConfigurationOptionType = 'unset';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n setName<K extends string>(name: K): ConfigurationOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ConfigurationOption<K>;\n }\n\n /**\n * Set the display name of the option. This is used to show the user a human readable version of what the option is. **REQUIRED**\n * @param displayName {string} The display name of the option.\n * @returns\n */\n setDisplayName(displayName: string): this {\n this.displayName = displayName;\n return this;\n }\n\n /**\n * Set the description of the option. This is to show the user a brief description of what this option does. **REQUIRED**\n * @param description {string} The description of the option.\n * @returns\n */\n setDescription(description: string): this {\n this.description = description;\n return this;\n }\n\n /**\n * Validation code for the option. This is called when the user provides input to the option. If the validation fails, the user will be prompted to provide input again.\n * @param input {unknown} The input to validate\n */\n validate(input: unknown): [boolean, string] {\n throw new Error('Validation code not implemented. Value: ' + input);\n }\n}\n\nexport class StringOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public allowedValues: string[] = [];\n public minTextLength: number = 0;\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: string = '';\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\n public type: ConfigurationOptionType = 'string';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): StringOption<K> {\n this.name = name as unknown as N;\n return this as unknown as StringOption<K>;\n }\n\n /**\n * Set the allowed values for the string. If the array is empty, any value is allowed. When provided, the client will act like this option is a dropdown.\n * @param allowedValues {string[]} An array of allowed values for the string. If the array is empty, any value is allowed.\n */\n setAllowedValues(allowedValues: string[]): this {\n this.allowedValues = allowedValues;\n return this;\n }\n\n /**\n * Set the default value for the string. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {string} The default value for the string.\n */\n setDefaultValue(defaultValue: string): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n /**\n * Set the minimum text length for the string. If the user provides a string that is less than this value, the validation will fail.\n * @param minTextLength {number} The minimum text length for the string.\n */\n setMinTextLength(minTextLength: number): this {\n this.minTextLength = minTextLength;\n return this;\n }\n\n /**\n * Set the maximum text length for the string. If the user provides a string that is greater than this value, the validation will fail.\n * @param maxTextLength {number} The maximum text length for the string.\n */\n setMaxTextLength(maxTextLength: number): this {\n this.maxTextLength = maxTextLength;\n return this;\n }\n\n /**\n * Set the input type for the string. This will change how the client renders the input.\n * @param inputType {'text' | 'file' | 'password' | 'folder'} The input type for the string.\n */\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\n this.inputType = inputType;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'string') {\n return [false, 'Input is not a string'];\n }\n if (this.allowedValues.length === 0 && input.length !== 0)\n return [true, ''];\n if (\n input.length < this.minTextLength ||\n input.length > this.maxTextLength\n ) {\n return [\n false,\n 'Input is not within the text length ' +\n this.minTextLength +\n ' and ' +\n this.maxTextLength +\n ' characters (currently ' +\n input.length +\n ' characters)',\n ];\n }\n\n return [\n this.allowedValues.includes(input),\n 'Input is not an allowed value',\n ];\n }\n}\n\nexport class NumberOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public min: number = 0;\n public max: number = Number.MAX_SAFE_INTEGER;\n public defaultValue: number = 0;\n public type: ConfigurationOptionType = 'number';\n public inputType: 'range' | 'number' = 'number';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): NumberOption<K> {\n this.name = name as unknown as N;\n return this as unknown as NumberOption<K>;\n }\n\n /**\n * Set the minimum value for the number. If the user provides a number that is less than this value, the validation will fail.\n * @param min {number} The minimum value for the number.\n */\n setMin(min: number): this {\n this.min = min;\n return this;\n }\n\n /**\n * Set the input type for the number. This will change how the client renders the input.\n * @param type {'range' | 'number'} The input type for the number.\n */\n setInputType(type: 'range' | 'number'): this {\n this.inputType = type;\n return this;\n }\n\n /**\n * Set the maximum value for the number. If the user provides a number that is greater than this value, the validation will fail.\n * @param max {number} The maximum value for the number.\n */\n setMax(max: number): this {\n this.max = max;\n return this;\n }\n\n /**\n * Set the default value for the number. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {number} The default value for the number.\n */\n setDefaultValue(defaultValue: number): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (isNaN(Number(input))) {\n return [false, 'Input is not a number'];\n }\n if (Number(input) < this.min || Number(input) > this.max) {\n return [\n false,\n 'Input is not within the range of ' + this.min + ' and ' + this.max,\n ];\n }\n return [true, ''];\n }\n}\n\nexport class BooleanOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'boolean';\n public defaultValue: boolean = false;\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): BooleanOption<K> {\n this.name = name as unknown as N;\n return this as unknown as BooleanOption<K>;\n }\n\n /**\n * Set the default value for the boolean. This value will be used if the user does not provide a value. **HIGHLY RECOMMENDED**\n * @param defaultValue {boolean} The default value for the boolean.\n */\n setDefaultValue(defaultValue: boolean): this {\n this.defaultValue = defaultValue;\n return this;\n }\n\n override validate(input: unknown): [boolean, string] {\n if (typeof input !== 'boolean') {\n return [false, 'Input is not a boolean'];\n }\n return [true, ''];\n }\n}\n\nexport class ActionOption<\n N extends string = string,\n> extends ConfigurationOption<N> {\n public type: ConfigurationOptionType = 'action';\n public manifest: Record<string, unknown> = {};\n public buttonText: string = 'Run';\n public taskName: string = '';\n\n /**\n * Set the name of the option. **REQUIRED**\n * @param name {string} The name of the option. This is used to reference the option in the configuration file.\n */\n override setName<K extends string>(name: K): ActionOption<K> {\n this.name = name as unknown as N;\n return this as unknown as ActionOption<K>;\n }\n\n /**\n * Set the task name that will be used to identify which task handler to run. This should match the name used in `addon.onTask()`.\n * @param taskName {string} The task name to identify the handler.\n */\n setTaskName(taskName: string): this {\n this.taskName = taskName;\n return this;\n }\n\n /**\n * Set the manifest object that will be passed to the task-run handler. The task name should be set via setTaskName() rather than in the manifest.\n * @param manifest {Record<string, unknown>} The manifest object to pass to the task handler.\n */\n setManifest(manifest: Record<string, unknown>): this {\n this.manifest = manifest;\n return this;\n }\n\n /**\n * Set the text displayed on the action button.\n * @param text {string} The button text.\n */\n setButtonText(text: string): this {\n this.buttonText = text;\n return this;\n }\n\n override validate(_input: unknown): [boolean, string] {\n return [true, ''];\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_chunk = require('./chunk-C0xms8kb.cjs');
3
+ let child_process = require("child_process");
4
+
5
+ //#region src/extraction.ts
6
+ const s7ZipPath = "C:\\Program Files\\7-Zip\\7z.exe";
7
+ function waitForChildProcess(childProcess, errorMessage) {
8
+ return new Promise((resolve, reject) => {
9
+ childProcess.once("error", reject);
10
+ childProcess.once("close", (code) => {
11
+ if (code !== 0) {
12
+ reject(new Error(errorMessage));
13
+ return;
14
+ }
15
+ resolve();
16
+ });
17
+ });
18
+ }
19
+ async function detectUnrarType() {
20
+ const childProcess = (0, child_process.spawn)("unrar");
21
+ return await new Promise((resolve, reject) => {
22
+ let output = "";
23
+ const collectOutput = (data) => {
24
+ output += data.toString();
25
+ };
26
+ childProcess.stdout.on("data", collectOutput);
27
+ childProcess.stderr.on("data", collectOutput);
28
+ childProcess.once("error", reject);
29
+ childProcess.once("close", () => {
30
+ if (output.includes("unrar-free")) {
31
+ resolve("unrar-free");
32
+ return;
33
+ }
34
+ if (output.includes("unrar-nonfree")) {
35
+ resolve("unrar-nonfree");
36
+ return;
37
+ }
38
+ resolve("unknown");
39
+ });
40
+ });
41
+ }
42
+ async function extraction(filePath, outputDir) {
43
+ const lowerCaseFilePath = filePath.toLowerCase();
44
+ if (process.platform === "win32") return await waitForChildProcess((0, child_process.spawn)(s7ZipPath, [
45
+ "x",
46
+ filePath,
47
+ "-o",
48
+ outputDir
49
+ ]), "Failed to extract file");
50
+ else if (process.platform === "linux" || process.platform === "darwin") {
51
+ if (lowerCaseFilePath.endsWith(".zip")) return await waitForChildProcess((0, child_process.spawn)("unzip", [
52
+ "-o",
53
+ filePath,
54
+ "-d",
55
+ outputDir
56
+ ]), "Failed to unzip file");
57
+ else if (lowerCaseFilePath.endsWith(".rar")) {
58
+ const unrarType = await detectUnrarType();
59
+ if (unrarType === "unrar-free") return await waitForChildProcess((0, child_process.spawn)("unrar", [
60
+ "-f",
61
+ "-x",
62
+ filePath,
63
+ outputDir
64
+ ]), "Failed to unrar file");
65
+ else if (unrarType === "unrar-nonfree") return await waitForChildProcess((0, child_process.spawn)("unrar", [
66
+ "-o",
67
+ filePath,
68
+ "-d",
69
+ outputDir
70
+ ]), "Failed to unrar file");
71
+ else throw new Error("Unknown unrar type");
72
+ }
73
+ throw new Error(`Unsupported archive type: ${filePath}`);
74
+ }
75
+ throw new Error(`Unsupported platform: ${process.platform}`);
76
+ }
77
+
78
+ //#endregion
79
+ exports.extraction = extraction;
80
+ //# sourceMappingURL=extraction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction.cjs","names":[],"sources":["../src/extraction.ts"],"sourcesContent":["import { spawn } from 'child_process';\n\nconst s7ZipPath = 'C:\\\\Program Files\\\\7-Zip\\\\7z.exe';\n\nfunction waitForChildProcess(\n childProcess: ReturnType<typeof spawn>,\n errorMessage: string\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n childProcess.once('error', reject);\n childProcess.once('close', (code) => {\n if (code !== 0) {\n reject(new Error(errorMessage));\n return;\n }\n\n resolve();\n });\n });\n}\n\nasync function detectUnrarType(): Promise<\n 'unrar-free' | 'unrar-nonfree' | 'unknown'\n> {\n const childProcess = spawn('unrar');\n\n return await new Promise((resolve, reject) => {\n let output = '';\n\n const collectOutput = (data: Buffer) => {\n output += data.toString();\n };\n\n childProcess.stdout.on('data', collectOutput);\n childProcess.stderr.on('data', collectOutput);\n childProcess.once('error', reject);\n childProcess.once('close', () => {\n if (output.includes('unrar-free')) {\n resolve('unrar-free');\n return;\n }\n\n if (output.includes('unrar-nonfree')) {\n resolve('unrar-nonfree');\n return;\n }\n\n resolve('unknown');\n });\n });\n}\n\nexport async function extraction(filePath: string, outputDir: string) {\n const lowerCaseFilePath = filePath.toLowerCase();\n\n if (process.platform === 'win32') {\n // expect 7zip to be installed, and use 7zip to unrar\n const childProcess = spawn(s7ZipPath, ['x', filePath, '-o', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to extract file');\n } else if (process.platform === 'linux' || process.platform === 'darwin') {\n if (lowerCaseFilePath.endsWith('.zip')) {\n // expect unzip to be installed, and use unzip to unzip\n const childProcess = spawn('unzip', ['-o', filePath, '-d', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unzip file');\n } else if (lowerCaseFilePath.endsWith('.rar')) {\n // check if unrar-nonfree is installed or unrar is installed\n const unrarType = await detectUnrarType();\n\n // now use the according unrar version to unrar\n if (unrarType === 'unrar-free') {\n // use unrar-free to unrar\n const childProcess = spawn('unrar', ['-f', '-x', filePath, outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unrar file');\n } else if (unrarType === 'unrar-nonfree') {\n // use unrar-nonfree to unrar\n const childProcess = spawn('unrar', ['-o', filePath, '-d', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unrar file');\n } else {\n throw new Error('Unknown unrar type');\n }\n }\n\n throw new Error(`Unsupported archive type: ${filePath}`);\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n}\n"],"mappings":";;;;;AAEA,MAAM,YAAY;AAElB,SAAS,oBACP,cACA,cACe;AACf,QAAO,IAAI,SAAe,SAAS,WAAW;AAC5C,eAAa,KAAK,SAAS,OAAO;AAClC,eAAa,KAAK,UAAU,SAAS;AACnC,OAAI,SAAS,GAAG;AACd,WAAO,IAAI,MAAM,aAAa,CAAC;AAC/B;;AAGF,YAAS;IACT;GACF;;AAGJ,eAAe,kBAEb;CACA,MAAM,wCAAqB,QAAQ;AAEnC,QAAO,MAAM,IAAI,SAAS,SAAS,WAAW;EAC5C,IAAI,SAAS;EAEb,MAAM,iBAAiB,SAAiB;AACtC,aAAU,KAAK,UAAU;;AAG3B,eAAa,OAAO,GAAG,QAAQ,cAAc;AAC7C,eAAa,OAAO,GAAG,QAAQ,cAAc;AAC7C,eAAa,KAAK,SAAS,OAAO;AAClC,eAAa,KAAK,eAAe;AAC/B,OAAI,OAAO,SAAS,aAAa,EAAE;AACjC,YAAQ,aAAa;AACrB;;AAGF,OAAI,OAAO,SAAS,gBAAgB,EAAE;AACpC,YAAQ,gBAAgB;AACxB;;AAGF,WAAQ,UAAU;IAClB;GACF;;AAGJ,eAAsB,WAAW,UAAkB,WAAmB;CACpE,MAAM,oBAAoB,SAAS,aAAa;AAEhD,KAAI,QAAQ,aAAa,QAGvB,QAAO,MAAM,6CADc,WAAW;EAAC;EAAK;EAAU;EAAM;EAAU,CAAC,EACxB,yBAAyB;UAC/D,QAAQ,aAAa,WAAW,QAAQ,aAAa,UAAU;AACxE,MAAI,kBAAkB,SAAS,OAAO,CAGpC,QAAO,MAAM,6CADc,SAAS;GAAC;GAAM;GAAU;GAAM;GAAU,CAAC,EACvB,uBAAuB;WAC7D,kBAAkB,SAAS,OAAO,EAAE;GAE7C,MAAM,YAAY,MAAM,iBAAiB;AAGzC,OAAI,cAAc,aAGhB,QAAO,MAAM,6CADc,SAAS;IAAC;IAAM;IAAM;IAAU;IAAU,CAAC,EACvB,uBAAuB;YAC7D,cAAc,gBAGvB,QAAO,MAAM,6CADc,SAAS;IAAC;IAAM;IAAU;IAAM;IAAU,CAAC,EACvB,uBAAuB;OAEtE,OAAM,IAAI,MAAM,qBAAqB;;AAIzC,QAAM,IAAI,MAAM,6BAA6B,WAAW;;AAG1D,OAAM,IAAI,MAAM,yBAAyB,QAAQ,WAAW"}
@@ -0,0 +1,5 @@
1
+ //#region src/extraction.d.ts
2
+ declare function extraction(filePath: string, outputDir: string): Promise<void>;
3
+ //#endregion
4
+ export { extraction };
5
+ //# sourceMappingURL=extraction.d.cts.map
@@ -0,0 +1,5 @@
1
+ //#region src/extraction.d.ts
2
+ declare function extraction(filePath: string, outputDir: string): Promise<void>;
3
+ //#endregion
4
+ export { extraction };
5
+ //# sourceMappingURL=extraction.d.mts.map
@@ -0,0 +1,78 @@
1
+ import { spawn } from "child_process";
2
+
3
+ //#region src/extraction.ts
4
+ const s7ZipPath = "C:\\Program Files\\7-Zip\\7z.exe";
5
+ function waitForChildProcess(childProcess, errorMessage) {
6
+ return new Promise((resolve, reject) => {
7
+ childProcess.once("error", reject);
8
+ childProcess.once("close", (code) => {
9
+ if (code !== 0) {
10
+ reject(new Error(errorMessage));
11
+ return;
12
+ }
13
+ resolve();
14
+ });
15
+ });
16
+ }
17
+ async function detectUnrarType() {
18
+ const childProcess = spawn("unrar");
19
+ return await new Promise((resolve, reject) => {
20
+ let output = "";
21
+ const collectOutput = (data) => {
22
+ output += data.toString();
23
+ };
24
+ childProcess.stdout.on("data", collectOutput);
25
+ childProcess.stderr.on("data", collectOutput);
26
+ childProcess.once("error", reject);
27
+ childProcess.once("close", () => {
28
+ if (output.includes("unrar-free")) {
29
+ resolve("unrar-free");
30
+ return;
31
+ }
32
+ if (output.includes("unrar-nonfree")) {
33
+ resolve("unrar-nonfree");
34
+ return;
35
+ }
36
+ resolve("unknown");
37
+ });
38
+ });
39
+ }
40
+ async function extraction(filePath, outputDir) {
41
+ const lowerCaseFilePath = filePath.toLowerCase();
42
+ if (process.platform === "win32") return await waitForChildProcess(spawn(s7ZipPath, [
43
+ "x",
44
+ filePath,
45
+ "-o",
46
+ outputDir
47
+ ]), "Failed to extract file");
48
+ else if (process.platform === "linux" || process.platform === "darwin") {
49
+ if (lowerCaseFilePath.endsWith(".zip")) return await waitForChildProcess(spawn("unzip", [
50
+ "-o",
51
+ filePath,
52
+ "-d",
53
+ outputDir
54
+ ]), "Failed to unzip file");
55
+ else if (lowerCaseFilePath.endsWith(".rar")) {
56
+ const unrarType = await detectUnrarType();
57
+ if (unrarType === "unrar-free") return await waitForChildProcess(spawn("unrar", [
58
+ "-f",
59
+ "-x",
60
+ filePath,
61
+ outputDir
62
+ ]), "Failed to unrar file");
63
+ else if (unrarType === "unrar-nonfree") return await waitForChildProcess(spawn("unrar", [
64
+ "-o",
65
+ filePath,
66
+ "-d",
67
+ outputDir
68
+ ]), "Failed to unrar file");
69
+ else throw new Error("Unknown unrar type");
70
+ }
71
+ throw new Error(`Unsupported archive type: ${filePath}`);
72
+ }
73
+ throw new Error(`Unsupported platform: ${process.platform}`);
74
+ }
75
+
76
+ //#endregion
77
+ export { extraction };
78
+ //# sourceMappingURL=extraction.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction.mjs","names":[],"sources":["../src/extraction.ts"],"sourcesContent":["import { spawn } from 'child_process';\n\nconst s7ZipPath = 'C:\\\\Program Files\\\\7-Zip\\\\7z.exe';\n\nfunction waitForChildProcess(\n childProcess: ReturnType<typeof spawn>,\n errorMessage: string\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n childProcess.once('error', reject);\n childProcess.once('close', (code) => {\n if (code !== 0) {\n reject(new Error(errorMessage));\n return;\n }\n\n resolve();\n });\n });\n}\n\nasync function detectUnrarType(): Promise<\n 'unrar-free' | 'unrar-nonfree' | 'unknown'\n> {\n const childProcess = spawn('unrar');\n\n return await new Promise((resolve, reject) => {\n let output = '';\n\n const collectOutput = (data: Buffer) => {\n output += data.toString();\n };\n\n childProcess.stdout.on('data', collectOutput);\n childProcess.stderr.on('data', collectOutput);\n childProcess.once('error', reject);\n childProcess.once('close', () => {\n if (output.includes('unrar-free')) {\n resolve('unrar-free');\n return;\n }\n\n if (output.includes('unrar-nonfree')) {\n resolve('unrar-nonfree');\n return;\n }\n\n resolve('unknown');\n });\n });\n}\n\nexport async function extraction(filePath: string, outputDir: string) {\n const lowerCaseFilePath = filePath.toLowerCase();\n\n if (process.platform === 'win32') {\n // expect 7zip to be installed, and use 7zip to unrar\n const childProcess = spawn(s7ZipPath, ['x', filePath, '-o', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to extract file');\n } else if (process.platform === 'linux' || process.platform === 'darwin') {\n if (lowerCaseFilePath.endsWith('.zip')) {\n // expect unzip to be installed, and use unzip to unzip\n const childProcess = spawn('unzip', ['-o', filePath, '-d', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unzip file');\n } else if (lowerCaseFilePath.endsWith('.rar')) {\n // check if unrar-nonfree is installed or unrar is installed\n const unrarType = await detectUnrarType();\n\n // now use the according unrar version to unrar\n if (unrarType === 'unrar-free') {\n // use unrar-free to unrar\n const childProcess = spawn('unrar', ['-f', '-x', filePath, outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unrar file');\n } else if (unrarType === 'unrar-nonfree') {\n // use unrar-nonfree to unrar\n const childProcess = spawn('unrar', ['-o', filePath, '-d', outputDir]);\n return await waitForChildProcess(childProcess, 'Failed to unrar file');\n } else {\n throw new Error('Unknown unrar type');\n }\n }\n\n throw new Error(`Unsupported archive type: ${filePath}`);\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n}\n"],"mappings":";;;AAEA,MAAM,YAAY;AAElB,SAAS,oBACP,cACA,cACe;AACf,QAAO,IAAI,SAAe,SAAS,WAAW;AAC5C,eAAa,KAAK,SAAS,OAAO;AAClC,eAAa,KAAK,UAAU,SAAS;AACnC,OAAI,SAAS,GAAG;AACd,WAAO,IAAI,MAAM,aAAa,CAAC;AAC/B;;AAGF,YAAS;IACT;GACF;;AAGJ,eAAe,kBAEb;CACA,MAAM,eAAe,MAAM,QAAQ;AAEnC,QAAO,MAAM,IAAI,SAAS,SAAS,WAAW;EAC5C,IAAI,SAAS;EAEb,MAAM,iBAAiB,SAAiB;AACtC,aAAU,KAAK,UAAU;;AAG3B,eAAa,OAAO,GAAG,QAAQ,cAAc;AAC7C,eAAa,OAAO,GAAG,QAAQ,cAAc;AAC7C,eAAa,KAAK,SAAS,OAAO;AAClC,eAAa,KAAK,eAAe;AAC/B,OAAI,OAAO,SAAS,aAAa,EAAE;AACjC,YAAQ,aAAa;AACrB;;AAGF,OAAI,OAAO,SAAS,gBAAgB,EAAE;AACpC,YAAQ,gBAAgB;AACxB;;AAGF,WAAQ,UAAU;IAClB;GACF;;AAGJ,eAAsB,WAAW,UAAkB,WAAmB;CACpE,MAAM,oBAAoB,SAAS,aAAa;AAEhD,KAAI,QAAQ,aAAa,QAGvB,QAAO,MAAM,oBADQ,MAAM,WAAW;EAAC;EAAK;EAAU;EAAM;EAAU,CAAC,EACxB,yBAAyB;UAC/D,QAAQ,aAAa,WAAW,QAAQ,aAAa,UAAU;AACxE,MAAI,kBAAkB,SAAS,OAAO,CAGpC,QAAO,MAAM,oBADQ,MAAM,SAAS;GAAC;GAAM;GAAU;GAAM;GAAU,CAAC,EACvB,uBAAuB;WAC7D,kBAAkB,SAAS,OAAO,EAAE;GAE7C,MAAM,YAAY,MAAM,iBAAiB;AAGzC,OAAI,cAAc,aAGhB,QAAO,MAAM,oBADQ,MAAM,SAAS;IAAC;IAAM;IAAM;IAAU;IAAU,CAAC,EACvB,uBAAuB;YAC7D,cAAc,gBAGvB,QAAO,MAAM,oBADQ,MAAM,SAAS;IAAC;IAAM;IAAU;IAAM;IAAU,CAAC,EACvB,uBAAuB;OAEtE,OAAM,IAAI,MAAM,qBAAqB;;AAIzC,QAAM,IAAI,MAAM,6BAA6B,WAAW;;AAG1D,OAAM,IAAI,MAAM,yBAAyB,QAAQ,WAAW"}
package/build/main.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
2
2
  const require_chunk = require('./chunk-C0xms8kb.cjs');
3
3
  const require_EventResponse = require('./EventResponse.cjs');
4
+ const require_extraction = require('./extraction.cjs');
4
5
  const require_config_ConfigurationBuilder = require('./config/ConfigurationBuilder.cjs');
5
6
  const require_config_Configuration = require('./config/Configuration.cjs');
6
7
  let ws = require("ws");
@@ -10,12 +11,9 @@ node_events = require_chunk.__toESM(node_events);
10
11
  let zod = require("zod");
11
12
  let fuse_js = require("fuse.js");
12
13
  fuse_js = require_chunk.__toESM(fuse_js);
13
- let node_child_process = require("node:child_process");
14
- let node_fs = require("node:fs");
15
- node_fs = require_chunk.__toESM(node_fs);
16
14
 
17
15
  //#region package.json
18
- var version = "2.4.0";
16
+ var version = "3.1.0";
19
17
 
20
18
  //#endregion
21
19
  //#region src/main.ts
@@ -152,83 +150,10 @@ var OGIAddon = class {
152
150
  * Extract a file using 7-Zip on Windows, unzip on Linux/Mac.
153
151
  * @param path {string}
154
152
  * @param outputPath {string}
155
- * @param type {'unrar' | 'unzip'}
156
153
  * @returns {Promise<void>}
157
154
  */
158
- async extractFile(path, outputPath, type) {
159
- return new Promise((resolve, reject) => {
160
- if (!node_fs.default.existsSync(outputPath)) node_fs.default.mkdirSync(outputPath, { recursive: true });
161
- if (type === "unzip") if (process.platform === "win32") (0, node_child_process.exec)(`"C:\\Program Files\\7-Zip\\7z.exe" x "${path}" -o"${outputPath}"`, (err, stdout, stderr) => {
162
- if (err) {
163
- console.error(err);
164
- console.log(stderr);
165
- reject(/* @__PURE__ */ new Error("Failed to extract ZIP file"));
166
- return;
167
- }
168
- console.log(stdout);
169
- console.log(stderr);
170
- resolve();
171
- });
172
- else {
173
- const unzipProcess = (0, node_child_process.spawn)("unzip", [
174
- "-o",
175
- path,
176
- "-d",
177
- outputPath
178
- ], { env: {
179
- ...process.env,
180
- UNZIP_DISABLE_ZIPBOMB_DETECTION: "TRUE"
181
- } });
182
- unzipProcess.stdout.on("data", (data) => {
183
- console.log(`[unzip stdout]: ${data}`);
184
- });
185
- unzipProcess.stderr.on("data", (data) => {
186
- console.error(`[unzip stderr]: ${data}`);
187
- });
188
- unzipProcess.on("close", (code) => {
189
- if (code !== 0) {
190
- console.error(`unzip process exited with code ${code}`);
191
- reject(/* @__PURE__ */ new Error("Failed to extract ZIP file"));
192
- return;
193
- }
194
- resolve();
195
- });
196
- }
197
- else if (type === "unrar") if (process.platform === "win32") (0, node_child_process.exec)(`"C:\\Program Files\\7-Zip\\7z.exe" x "${path}" -o"${outputPath}"`, (err, stdout, stderr) => {
198
- if (err) {
199
- console.error(err);
200
- console.log(stderr);
201
- reject(/* @__PURE__ */ new Error("Failed to extract RAR file"));
202
- return;
203
- }
204
- console.log(stdout);
205
- console.log(stderr);
206
- resolve();
207
- });
208
- else {
209
- const unrarProcess = (0, node_child_process.spawn)("unrar", [
210
- "x",
211
- "-y",
212
- path,
213
- outputPath
214
- ]);
215
- unrarProcess.stdout.on("data", (data) => {
216
- console.log(`[unrar stdout]: ${data}`);
217
- });
218
- unrarProcess.stderr.on("data", (data) => {
219
- console.error(`[unrar stderr]: ${data}`);
220
- });
221
- unrarProcess.on("close", (code) => {
222
- if (code !== 0) {
223
- console.error(`unrar process exited with code ${code}`);
224
- reject(/* @__PURE__ */ new Error("Failed to extract RAR file"));
225
- return;
226
- }
227
- resolve();
228
- });
229
- }
230
- else reject(/* @__PURE__ */ new Error("Unknown extraction type"));
231
- });
155
+ async extractFile(path, outputPath) {
156
+ return await require_extraction.extraction(path, outputPath);
232
157
  }
233
158
  };
234
159
  /**
@@ -364,20 +289,20 @@ const ZodLibraryInfo = zod.z.object({
364
289
  appID: zod.z.number(),
365
290
  launchExecutable: zod.z.string(),
366
291
  launchArguments: zod.z.string().optional(),
292
+ launchEnv: zod.z.record(zod.z.string(), zod.z.string()).optional(),
367
293
  capsuleImage: zod.z.string(),
368
294
  storefront: zod.z.string(),
369
295
  addonsource: zod.z.string(),
370
296
  coverImage: zod.z.string(),
371
297
  titleImage: zod.z.string().optional(),
372
298
  umu: zod.z.object({
373
- umuId: zod.z.string().regex(/^(steam|umu):\d+$/, "Must be in format steam:{number} or umu:{number}"),
299
+ umuId: zod.z.string().regex(/^(steam|umu):\S+$/, "Must be in format steam:{number} or umu:{string | number}"),
374
300
  dllOverrides: zod.z.array(zod.z.string()).optional(),
375
301
  protonVersion: zod.z.string().optional(),
376
302
  store: zod.z.string().optional(),
377
303
  winePrefixPath: zod.z.string().optional(),
378
304
  steamShortcutId: zod.z.number().optional()
379
305
  }).optional(),
380
- legacyMode: zod.z.boolean().optional(),
381
306
  redistributables: zod.z.array(zod.z.object({
382
307
  name: zod.z.string(),
383
308
  path: zod.z.string()
@@ -653,4 +578,5 @@ exports.Task = Task;
653
578
  exports.VERSION = VERSION;
654
579
  exports.ZodLibraryInfo = ZodLibraryInfo;
655
580
  exports.default = OGIAddon;
581
+ exports.extraction = require_extraction.extraction;
656
582
  //# sourceMappingURL=main.cjs.map