@ducky7go/ducky-cli 0.0.1
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.
- package/LICENSE +661 -0
- package/README.md +241 -0
- package/bin/ducky +25 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/nuget/index.d.ts +3 -0
- package/dist/commands/nuget/index.d.ts.map +1 -0
- package/dist/commands/nuget/index.js +23 -0
- package/dist/commands/nuget/index.js.map +1 -0
- package/dist/commands/nuget/pack.d.ts +7 -0
- package/dist/commands/nuget/pack.d.ts.map +1 -0
- package/dist/commands/nuget/pack.js +78 -0
- package/dist/commands/nuget/pack.js.map +1 -0
- package/dist/commands/nuget/push.d.ts +7 -0
- package/dist/commands/nuget/push.d.ts.map +1 -0
- package/dist/commands/nuget/push.js +110 -0
- package/dist/commands/nuget/push.js.map +1 -0
- package/dist/commands/nuget/validate.d.ts +7 -0
- package/dist/commands/nuget/validate.d.ts.map +1 -0
- package/dist/commands/nuget/validate.js +78 -0
- package/dist/commands/nuget/validate.js.map +1 -0
- package/dist/formats/index.d.ts +2 -0
- package/dist/formats/index.d.ts.map +1 -0
- package/dist/formats/index.js +6 -0
- package/dist/formats/index.js.map +1 -0
- package/dist/formats/nuget/client.d.ts +59 -0
- package/dist/formats/nuget/client.d.ts.map +1 -0
- package/dist/formats/nuget/client.js +202 -0
- package/dist/formats/nuget/client.js.map +1 -0
- package/dist/formats/nuget/collector.d.ts +36 -0
- package/dist/formats/nuget/collector.d.ts.map +1 -0
- package/dist/formats/nuget/collector.js +72 -0
- package/dist/formats/nuget/collector.js.map +1 -0
- package/dist/formats/nuget/index.d.ts +6 -0
- package/dist/formats/nuget/index.d.ts.map +1 -0
- package/dist/formats/nuget/index.js +11 -0
- package/dist/formats/nuget/index.js.map +1 -0
- package/dist/formats/nuget/nuspec.d.ts +10 -0
- package/dist/formats/nuget/nuspec.d.ts.map +1 -0
- package/dist/formats/nuget/nuspec.js +59 -0
- package/dist/formats/nuget/nuspec.js.map +1 -0
- package/dist/formats/nuget/parser.d.ts +31 -0
- package/dist/formats/nuget/parser.d.ts.map +1 -0
- package/dist/formats/nuget/parser.js +140 -0
- package/dist/formats/nuget/parser.js.map +1 -0
- package/dist/formats/nuget/validator.d.ts +19 -0
- package/dist/formats/nuget/validator.d.ts.map +1 -0
- package/dist/formats/nuget/validator.js +104 -0
- package/dist/formats/nuget/validator.js.map +1 -0
- package/dist/utils/config.d.ts +31 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +86 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/errors.d.ts +43 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +73 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/fs.d.ts +42 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +125 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +71 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +119 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { readTextFile } from '../../utils/fs.js';
|
|
2
|
+
import { FileSystemError, ValidationError } from '../../utils/errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parse info.ini file from a mod directory
|
|
5
|
+
* @param modPath - Path to the mod directory
|
|
6
|
+
* @returns Parsed metadata
|
|
7
|
+
* @throws {FileSystemError} If info.ini is not found
|
|
8
|
+
* @throws {ValidationError} If required fields are missing
|
|
9
|
+
*/
|
|
10
|
+
export async function parseInfoIni(modPath) {
|
|
11
|
+
const infoIniPath = `${modPath}/info.ini`;
|
|
12
|
+
try {
|
|
13
|
+
const content = await readTextFile(infoIniPath);
|
|
14
|
+
return parseInfoIniContent(content);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (error instanceof FileSystemError) {
|
|
18
|
+
throw new FileSystemError(`info.ini not found in ${modPath}`, [
|
|
19
|
+
'Ensure info.ini exists in the mod directory',
|
|
20
|
+
'The info.ini file should contain mod metadata',
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parse info.ini content
|
|
28
|
+
* @param content - Raw INI content
|
|
29
|
+
* @returns Parsed metadata
|
|
30
|
+
* @throws {ValidationError} If required fields are missing or invalid
|
|
31
|
+
*/
|
|
32
|
+
export function parseInfoIniContent(content) {
|
|
33
|
+
const ini = parseIni(content);
|
|
34
|
+
const metadata = ini[''];
|
|
35
|
+
if (!metadata) {
|
|
36
|
+
throw new ValidationError('info.ini is empty or invalid', ['Ensure info.ini contains metadata fields']);
|
|
37
|
+
}
|
|
38
|
+
// Validate required fields
|
|
39
|
+
const requiredFields = ['name', 'version'];
|
|
40
|
+
const missingFields = requiredFields.filter((field) => !metadata[field]);
|
|
41
|
+
if (missingFields.length > 0) {
|
|
42
|
+
throw new ValidationError(`Missing required fields in info.ini: ${missingFields.join(', ')}`, [
|
|
43
|
+
'Add the missing fields to info.ini',
|
|
44
|
+
'Required fields: name, version',
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
// Validate name (NuGet ID format)
|
|
48
|
+
const name = metadata.name.trim();
|
|
49
|
+
if (!isValidNuGetId(name)) {
|
|
50
|
+
throw new ValidationError(`Invalid NuGet ID: ${name}`, [
|
|
51
|
+
'NuGet IDs must start with a letter or underscore',
|
|
52
|
+
'Allowed characters: letters, digits, dots, hyphens, underscores',
|
|
53
|
+
'Example: MyMod.Example',
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
// Validate version (SemVer 2.0)
|
|
57
|
+
const version = metadata.version.trim();
|
|
58
|
+
if (!isValidSemVer(version)) {
|
|
59
|
+
throw new ValidationError(`Invalid version format: ${version}`, [
|
|
60
|
+
'Version must follow SemVer 2.0 format',
|
|
61
|
+
'Example: 1.0.0, 2.1.0-beta, 3.0.0-rc.1',
|
|
62
|
+
]);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
name,
|
|
66
|
+
version,
|
|
67
|
+
description: metadata.description?.trim(),
|
|
68
|
+
author: metadata.author?.trim(),
|
|
69
|
+
icon: metadata.icon?.trim(),
|
|
70
|
+
tags: parseList(metadata.tags),
|
|
71
|
+
dependencies: parseList(metadata.dependencies),
|
|
72
|
+
projectUrl: metadata.projectUrl?.trim(),
|
|
73
|
+
license: metadata.license?.trim(),
|
|
74
|
+
copyright: metadata.copyright?.trim(),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Simple INI parser
|
|
79
|
+
* @param content - Raw INI content
|
|
80
|
+
* @returns Parsed INI object
|
|
81
|
+
*/
|
|
82
|
+
function parseIni(content) {
|
|
83
|
+
const result = { '': {} };
|
|
84
|
+
let currentSection = '';
|
|
85
|
+
for (const line of content.split('\n')) {
|
|
86
|
+
const trimmed = line.trim();
|
|
87
|
+
const commentIndex = trimmed.indexOf('#');
|
|
88
|
+
const activeLine = commentIndex >= 0 ? trimmed.slice(0, commentIndex).trim() : trimmed;
|
|
89
|
+
if (!activeLine) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
// Section header
|
|
93
|
+
const sectionMatch = activeLine.match(/^\[([^\]]+)\]$/);
|
|
94
|
+
if (sectionMatch) {
|
|
95
|
+
currentSection = sectionMatch[1];
|
|
96
|
+
result[currentSection] = {};
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Key-value pair
|
|
100
|
+
const keyValueMatch = activeLine.match(/^([^=]+)=(.*)$/);
|
|
101
|
+
if (keyValueMatch) {
|
|
102
|
+
const key = keyValueMatch[1].trim();
|
|
103
|
+
const value = keyValueMatch[2].trim();
|
|
104
|
+
result[currentSection][key] = value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Parse a comma-separated list
|
|
111
|
+
*/
|
|
112
|
+
function parseList(value) {
|
|
113
|
+
if (!value) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
return value
|
|
117
|
+
.split(',')
|
|
118
|
+
.map((item) => item.trim())
|
|
119
|
+
.filter((item) => item.length > 0);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Validate NuGet ID format
|
|
123
|
+
* Based on: https://learn.microsoft.com/en-us/nuget/reference/id-prefixes
|
|
124
|
+
*/
|
|
125
|
+
function isValidNuGetId(id) {
|
|
126
|
+
if (!id || id.length > 100) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return /^[A-Za-z_][A-Za-z0-9._-]*$/.test(id);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Validate SemVer 2.0 version format
|
|
133
|
+
* Based on: https://semver.org/spec/v2.0.0.html
|
|
134
|
+
*/
|
|
135
|
+
function isValidSemVer(version) {
|
|
136
|
+
// SemVer regex pattern
|
|
137
|
+
const semverPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
138
|
+
return semverPattern.test(version);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/formats/nuget/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ModMetadata } from './parser.js';
|
|
2
|
+
import { ValidationError } from '../../utils/errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validation result
|
|
5
|
+
*/
|
|
6
|
+
export interface ValidationResult {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
errors: ValidationError[];
|
|
9
|
+
warnings: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validate a mod directory according to NuGet Mod Packaging Specification v1.0
|
|
13
|
+
*
|
|
14
|
+
* @param modPath - Path to mod directory
|
|
15
|
+
* @param metadata - Parsed metadata
|
|
16
|
+
* @returns Validation result
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateMod(modPath: string, metadata: ModMetadata): Promise<ValidationResult>;
|
|
19
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/formats/nuget/validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAqB3B"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { collectFiles } from '../../utils/fs.js';
|
|
2
|
+
import { ValidationError } from '../../utils/errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate a mod directory according to NuGet Mod Packaging Specification v1.0
|
|
5
|
+
*
|
|
6
|
+
* @param modPath - Path to mod directory
|
|
7
|
+
* @param metadata - Parsed metadata
|
|
8
|
+
* @returns Validation result
|
|
9
|
+
*/
|
|
10
|
+
export async function validateMod(modPath, metadata) {
|
|
11
|
+
const errors = [];
|
|
12
|
+
const warnings = [];
|
|
13
|
+
// 1. Validate DLL name matches mod name
|
|
14
|
+
await validateDllName(modPath, metadata, errors);
|
|
15
|
+
// 2. Validate version format (already done in parser, but double-check)
|
|
16
|
+
validateSemVer(metadata.version, errors);
|
|
17
|
+
// 3. Validate NuGet ID (already done in parser, but double-check)
|
|
18
|
+
validateNuGetId(metadata.name, errors);
|
|
19
|
+
// 4. Validate required fields
|
|
20
|
+
validateRequiredFields(metadata, errors);
|
|
21
|
+
return {
|
|
22
|
+
valid: errors.length === 0,
|
|
23
|
+
errors,
|
|
24
|
+
warnings,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate that at least one DLL exists and its name matches the mod name
|
|
29
|
+
*/
|
|
30
|
+
async function validateDllName(modPath, metadata, errors) {
|
|
31
|
+
const dllFiles = await collectFiles(modPath, /\.dll$/i);
|
|
32
|
+
if (dllFiles.length === 0) {
|
|
33
|
+
errors.push(new ValidationError('No DLL files found in mod directory', [
|
|
34
|
+
'Add at least one DLL file to the mod',
|
|
35
|
+
'DLL files are required for game mods',
|
|
36
|
+
]));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Check if any DLL name matches the mod name
|
|
40
|
+
const expectedDllName = metadata.name;
|
|
41
|
+
const hasMatchingDll = dllFiles.some((dllPath) => {
|
|
42
|
+
const fileName = dllPath.split('/').pop() || dllPath.split('\\').pop() || '';
|
|
43
|
+
const baseName = fileName.replace(/\.dll$/i, '');
|
|
44
|
+
return baseName === expectedDllName;
|
|
45
|
+
});
|
|
46
|
+
if (!hasMatchingDll) {
|
|
47
|
+
const dllNames = dllFiles
|
|
48
|
+
.map((p) => p.split('/').pop() || p.split('\\').pop() || '')
|
|
49
|
+
.join(', ');
|
|
50
|
+
errors.push(new ValidationError(`No DLL file matches mod name "${metadata.name}"`, [
|
|
51
|
+
`Rename one of the DLLs to "${metadata.name}.dll"`,
|
|
52
|
+
`Current DLLs: ${dllNames}`,
|
|
53
|
+
]));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate SemVer 2.0 version format
|
|
58
|
+
*/
|
|
59
|
+
function validateSemVer(version, errors) {
|
|
60
|
+
const semverPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
61
|
+
if (!semverPattern.test(version)) {
|
|
62
|
+
errors.push(new ValidationError(`Invalid version format: ${version}`, [
|
|
63
|
+
'Version must follow SemVer 2.0 format',
|
|
64
|
+
'Examples: 1.0.0, 2.1.0-beta, 3.0.0-rc.1+build.123',
|
|
65
|
+
]));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validate NuGet ID format
|
|
70
|
+
*/
|
|
71
|
+
function validateNuGetId(id, errors) {
|
|
72
|
+
if (!id || id.length > 100) {
|
|
73
|
+
errors.push(new ValidationError(`Invalid NuGet ID length: ${id ? id.length : 0} characters (max 100)`, ['Use a shorter name for your mod']));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!/^[A-Za-z_][A-Za-z0-9._-]*$/.test(id)) {
|
|
77
|
+
errors.push(new ValidationError(`Invalid NuGet ID format: ${id}`, [
|
|
78
|
+
'NuGet IDs must start with a letter or underscore',
|
|
79
|
+
'Allowed characters: letters, digits, dots, hyphens, underscores',
|
|
80
|
+
'Example: MyMod.Example',
|
|
81
|
+
]));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Validate required fields are present
|
|
86
|
+
*/
|
|
87
|
+
function validateRequiredFields(metadata, errors) {
|
|
88
|
+
if (!metadata.name) {
|
|
89
|
+
errors.push(new ValidationError('Missing required field: name', [
|
|
90
|
+
'Add "name" field to info.ini',
|
|
91
|
+
]));
|
|
92
|
+
}
|
|
93
|
+
if (!metadata.version) {
|
|
94
|
+
errors.push(new ValidationError('Missing required field: version', [
|
|
95
|
+
'Add "version" field to info.ini',
|
|
96
|
+
]));
|
|
97
|
+
}
|
|
98
|
+
if (!metadata.description) {
|
|
99
|
+
errors.push(new ValidationError('Missing recommended field: description', [
|
|
100
|
+
'Add "description" field to info.ini',
|
|
101
|
+
]));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/formats/nuget/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration interface for NuGet operations
|
|
3
|
+
*/
|
|
4
|
+
export interface NuGetConfig {
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
server?: string;
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve configuration from multiple sources with precedence:
|
|
11
|
+
* 1. CLI flags (highest priority)
|
|
12
|
+
* 2. Environment variables
|
|
13
|
+
* 3. Config file (.duckyrc)
|
|
14
|
+
* 4. Default values (lowest priority)
|
|
15
|
+
*
|
|
16
|
+
* @param cliFlags - Configuration from CLI flags
|
|
17
|
+
* @param envPrefix - Prefix for environment variables (default: 'NUGET')
|
|
18
|
+
* @returns Resolved configuration
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveConfig(cliFlags?: Partial<NuGetConfig>, envPrefix?: string): NuGetConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Get API key from configuration
|
|
23
|
+
* @throws {ConfigError} If API key is required but not found
|
|
24
|
+
*/
|
|
25
|
+
export declare function getApiKey(config: NuGetConfig): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get server URL from configuration
|
|
28
|
+
* @throws {ConfigError} If server URL is invalid
|
|
29
|
+
*/
|
|
30
|
+
export declare function getServerUrl(config: NuGetConfig): string;
|
|
31
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,GAAE,OAAO,CAAC,WAAW,CAAM,EACnC,SAAS,SAAU,GAClB,WAAW,CAqCb;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAYrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAcxD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { config as dotenvConfig } from 'dotenv';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { ConfigError } from './errors.js';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
// Load .env file if it exists
|
|
8
|
+
dotenvConfig();
|
|
9
|
+
/**
|
|
10
|
+
* Resolve configuration from multiple sources with precedence:
|
|
11
|
+
* 1. CLI flags (highest priority)
|
|
12
|
+
* 2. Environment variables
|
|
13
|
+
* 3. Config file (.duckyrc)
|
|
14
|
+
* 4. Default values (lowest priority)
|
|
15
|
+
*
|
|
16
|
+
* @param cliFlags - Configuration from CLI flags
|
|
17
|
+
* @param envPrefix - Prefix for environment variables (default: 'NUGET')
|
|
18
|
+
* @returns Resolved configuration
|
|
19
|
+
*/
|
|
20
|
+
export function resolveConfig(cliFlags = {}, envPrefix = 'NUGET') {
|
|
21
|
+
const config = {
|
|
22
|
+
// Default values
|
|
23
|
+
server: 'https://api.nuget.org/v3/index.json',
|
|
24
|
+
verbose: false,
|
|
25
|
+
};
|
|
26
|
+
// Load from environment variables
|
|
27
|
+
const envApiKey = process.env[`${envPrefix}_API_KEY`];
|
|
28
|
+
const envServer = process.env[`${envPrefix}_SERVER`];
|
|
29
|
+
const envVerbose = process.env[`${envPrefix}_VERBOSE`];
|
|
30
|
+
if (envApiKey) {
|
|
31
|
+
config.apiKey = envApiKey;
|
|
32
|
+
}
|
|
33
|
+
if (envServer) {
|
|
34
|
+
config.server = envServer;
|
|
35
|
+
}
|
|
36
|
+
if (envVerbose) {
|
|
37
|
+
config.verbose = envVerbose === 'true' || envVerbose === '1';
|
|
38
|
+
}
|
|
39
|
+
// Load from config file (optional)
|
|
40
|
+
// TODO: Implement .duckyrc parsing if needed
|
|
41
|
+
// Override with CLI flags (highest priority)
|
|
42
|
+
if (cliFlags.apiKey !== undefined) {
|
|
43
|
+
config.apiKey = cliFlags.apiKey;
|
|
44
|
+
}
|
|
45
|
+
if (cliFlags.server !== undefined) {
|
|
46
|
+
config.server = cliFlags.server;
|
|
47
|
+
}
|
|
48
|
+
if (cliFlags.verbose !== undefined) {
|
|
49
|
+
config.verbose = cliFlags.verbose;
|
|
50
|
+
}
|
|
51
|
+
return config;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get API key from configuration
|
|
55
|
+
* @throws {ConfigError} If API key is required but not found
|
|
56
|
+
*/
|
|
57
|
+
export function getApiKey(config) {
|
|
58
|
+
if (!config.apiKey) {
|
|
59
|
+
throw new ConfigError('NuGet API key is required for this operation', [
|
|
60
|
+
'Set the NUGET_API_KEY environment variable',
|
|
61
|
+
'Use the --api-key flag',
|
|
62
|
+
'For nuget.org, create an API key at https://www.nuget.org/account/apikeys',
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
return config.apiKey;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get server URL from configuration
|
|
69
|
+
* @throws {ConfigError} If server URL is invalid
|
|
70
|
+
*/
|
|
71
|
+
export function getServerUrl(config) {
|
|
72
|
+
if (!config.server) {
|
|
73
|
+
return 'https://api.nuget.org/v3/index.json';
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
new URL(config.server);
|
|
77
|
+
return config.server;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
throw new ConfigError(`Invalid server URL: ${config.server}`, [
|
|
81
|
+
'Ensure the URL is valid (e.g., https://api.nuget.org/v3/index.json)',
|
|
82
|
+
'Use the --server flag with a valid URL',
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAW,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,8BAA8B;AAC9B,YAAY,EAAE,CAAC;AAWf;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAiC,EAAE,EACnC,SAAS,GAAG,OAAO;IAEnB,MAAM,MAAM,GAAgB;QAC1B,iBAAiB;QACjB,MAAM,EAAE,qCAAqC;QAC7C,OAAO,EAAE,KAAK;KACf,CAAC;IAEF,kCAAkC;IAClC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;IAEvD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,GAAG,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,GAAG,CAAC;IAC/D,CAAC;IAED,mCAAmC;IACnC,6CAA6C;IAE7C,6CAA6C;IAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACpC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,WAAW,CACnB,8CAA8C,EAC9C;YACE,4CAA4C;YAC5C,wBAAwB;YACxB,2EAA2E;SAC5E,CACF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,qCAAqC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,uBAAuB,MAAM,CAAC,MAAM,EAAE,EAAE;YAC5D,qEAAqE;YACrE,wCAAwC;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all ducky-cli errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class DuckyError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly suggestions?: string[] | undefined;
|
|
7
|
+
constructor(message: string, code: string, suggestions?: string[] | undefined);
|
|
8
|
+
/**
|
|
9
|
+
* Format the error with suggestions for user-friendly display
|
|
10
|
+
*/
|
|
11
|
+
format(): string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Error raised when mod validation fails
|
|
15
|
+
*/
|
|
16
|
+
export declare class ValidationError extends DuckyError {
|
|
17
|
+
constructor(message: string, suggestions?: string[]);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error raised when configuration is missing or invalid
|
|
21
|
+
*/
|
|
22
|
+
export declare class ConfigError extends DuckyError {
|
|
23
|
+
constructor(message: string, suggestions?: string[]);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error raised when network operations fail
|
|
27
|
+
*/
|
|
28
|
+
export declare class NetworkError extends DuckyError {
|
|
29
|
+
constructor(message: string, suggestions?: string[]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Error raised when file system operations fail
|
|
33
|
+
*/
|
|
34
|
+
export declare class FileSystemError extends DuckyError {
|
|
35
|
+
constructor(message: string, suggestions?: string[]);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Error raised when NuGet CLI operations fail
|
|
39
|
+
*/
|
|
40
|
+
export declare class NuGetError extends DuckyError {
|
|
41
|
+
constructor(message: string, suggestions?: string[]);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,IAAI,EAAE,MAAM;aACZ,WAAW,CAAC,EAAE,MAAM,EAAE;gBAFtC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,EAAE,YAAA;IAOxC;;OAEG;IACH,MAAM,IAAI,MAAM;CAUjB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAIpD;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,UAAU;gBAC7B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAIpD;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,UAAU;gBAC9B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAIpD;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAIpD;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,UAAU;gBAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAIpD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all ducky-cli errors
|
|
3
|
+
*/
|
|
4
|
+
export class DuckyError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
suggestions;
|
|
7
|
+
constructor(message, code, suggestions) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.suggestions = suggestions;
|
|
11
|
+
this.name = 'DuckyError';
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Format the error with suggestions for user-friendly display
|
|
16
|
+
*/
|
|
17
|
+
format() {
|
|
18
|
+
let output = `\x1b[31m✖ ${this.message}\x1b[0m`;
|
|
19
|
+
if (this.suggestions && this.suggestions.length > 0) {
|
|
20
|
+
output += '\n\nSuggestions:';
|
|
21
|
+
for (const suggestion of this.suggestions) {
|
|
22
|
+
output += `\n • ${suggestion}`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return output;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Error raised when mod validation fails
|
|
30
|
+
*/
|
|
31
|
+
export class ValidationError extends DuckyError {
|
|
32
|
+
constructor(message, suggestions) {
|
|
33
|
+
super(message, 'VALIDATION_ERROR', suggestions);
|
|
34
|
+
this.name = 'ValidationError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Error raised when configuration is missing or invalid
|
|
39
|
+
*/
|
|
40
|
+
export class ConfigError extends DuckyError {
|
|
41
|
+
constructor(message, suggestions) {
|
|
42
|
+
super(message, 'CONFIG_ERROR', suggestions);
|
|
43
|
+
this.name = 'ConfigError';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Error raised when network operations fail
|
|
48
|
+
*/
|
|
49
|
+
export class NetworkError extends DuckyError {
|
|
50
|
+
constructor(message, suggestions) {
|
|
51
|
+
super(message, 'NETWORK_ERROR', suggestions);
|
|
52
|
+
this.name = 'NetworkError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error raised when file system operations fail
|
|
57
|
+
*/
|
|
58
|
+
export class FileSystemError extends DuckyError {
|
|
59
|
+
constructor(message, suggestions) {
|
|
60
|
+
super(message, 'FILESYSTEM_ERROR', suggestions);
|
|
61
|
+
this.name = 'FileSystemError';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Error raised when NuGet CLI operations fail
|
|
66
|
+
*/
|
|
67
|
+
export class NuGetError extends DuckyError {
|
|
68
|
+
constructor(message, suggestions) {
|
|
69
|
+
super(message, 'NUGET_ERROR', suggestions);
|
|
70
|
+
this.name = 'NuGetError';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IACA;IAHlB,YACE,OAAe,EACC,IAAY,EACZ,WAAsB;QAEtC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAQ;QACZ,gBAAW,GAAX,WAAW,CAAW;QAGtC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,MAAM,GAAG,aAAa,IAAI,CAAC,OAAO,SAAS,CAAC;QAChD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,kBAAkB,CAAC;YAC7B,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1C,MAAM,IAAI,SAAS,UAAU,EAAE,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAC7C,YAAY,OAAe,EAAE,WAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YAAY,OAAe,EAAE,WAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,UAAU;IAC1C,YAAY,OAAe,EAAE,WAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAC7C,YAAY,OAAe,EAAE,WAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,UAAU;IACxC,YAAY,OAAe,EAAE,WAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a file exists
|
|
3
|
+
*/
|
|
4
|
+
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Check if a directory exists
|
|
7
|
+
*/
|
|
8
|
+
export declare function directoryExists(dirPath: string): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* Synchronously check if a file exists (for convenience)
|
|
11
|
+
*/
|
|
12
|
+
export declare function fileExistsSync(filePath: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Validate a file path to prevent directory traversal attacks
|
|
15
|
+
* @throws {FileSystemError} If path contains directory traversal patterns
|
|
16
|
+
*/
|
|
17
|
+
export declare function validatePath(basePath: string, targetPath: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Recursively collect files matching a pattern
|
|
20
|
+
*/
|
|
21
|
+
export declare function collectFiles(dirPath: string, pattern?: RegExp): Promise<string[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Read a file as text
|
|
24
|
+
*/
|
|
25
|
+
export declare function readTextFile(filePath: string): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Ensure a directory exists, creating it if necessary
|
|
28
|
+
*/
|
|
29
|
+
export declare function ensureDirectory(dirPath: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the size of a file in bytes
|
|
32
|
+
*/
|
|
33
|
+
export declare function getFileSize(filePath: string): Promise<number>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a path is a directory
|
|
36
|
+
*/
|
|
37
|
+
export declare function isDirectory(path: string): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a path is a file
|
|
40
|
+
*/
|
|
41
|
+
export declare function isFile(path: string): Promise<boolean>;
|
|
42
|
+
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAYzE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAa,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBnB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASpE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASpE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOhE;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3D"}
|