gitlab-catalog-browser 0.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.
- package/LICENSE +201 -0
- package/README.md +75 -0
- package/bin/gitlab-ci-cli.js +29 -0
- package/dist/api/catalog.d.ts +38 -0
- package/dist/api/catalog.d.ts.map +1 -0
- package/dist/api/catalog.js +72 -0
- package/dist/api/catalog.js.map +1 -0
- package/dist/api/gitlab.d.ts +69 -0
- package/dist/api/gitlab.d.ts.map +1 -0
- package/dist/api/gitlab.js +226 -0
- package/dist/api/gitlab.js.map +1 -0
- package/dist/api/lint.d.ts +61 -0
- package/dist/api/lint.d.ts.map +1 -0
- package/dist/api/lint.js +41 -0
- package/dist/api/lint.js.map +1 -0
- package/dist/cache/schema-cache.d.ts +54 -0
- package/dist/cache/schema-cache.d.ts.map +1 -0
- package/dist/cache/schema-cache.js +124 -0
- package/dist/cache/schema-cache.js.map +1 -0
- package/dist/commands/batch.d.ts +19 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +174 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/catalog.d.ts +42 -0
- package/dist/commands/catalog.d.ts.map +1 -0
- package/dist/commands/catalog.js +158 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/component.d.ts +46 -0
- package/dist/commands/component.d.ts.map +1 -0
- package/dist/commands/component.js +213 -0
- package/dist/commands/component.js.map +1 -0
- package/dist/commands/pipeline.d.ts +61 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +880 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/setup.d.ts +119 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +391 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/skills.d.ts +39 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +208 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/validate.d.ts +27 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +201 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/loader.d.ts +80 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +217 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +46 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +45 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +437 -0
- package/dist/index.js.map +1 -0
- package/dist/output/table.d.ts +28 -0
- package/dist/output/table.d.ts.map +1 -0
- package/dist/output/table.js +67 -0
- package/dist/output/table.js.map +1 -0
- package/dist/types/api.d.ts +66 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +61 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/catalog.d.ts +77 -0
- package/dist/types/catalog.d.ts.map +1 -0
- package/dist/types/catalog.js +5 -0
- package/dist/types/catalog.js.map +1 -0
- package/package.json +60 -0
- package/skill-data/core/reference.md +127 -0
- package/skill-data/core/templates.md +97 -0
- package/skill-data/core/workflows.md +84 -0
- package/skill-data/manifest.json +12 -0
- package/skill-data/templates/basic-pipeline.yml +29 -0
- package/skill-data/templates/docker-build.yml +38 -0
- package/skill-data/templates/multi-stage.yml +43 -0
- package/skills/gitlab-catalog-browser/SKILL.md +49 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Skill Integration command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `skills list`, `skills get`, and `skills path` commands
|
|
5
|
+
* for serving AI agent workflow content.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
8
|
+
import { readdirSync } from 'node:fs';
|
|
9
|
+
import { join, dirname, resolve } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
// ──────────────────────────────────────────────
|
|
12
|
+
// Path resolution
|
|
13
|
+
// ──────────────────────────────────────────────
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the skills data directory path.
|
|
18
|
+
* Priority: GITLAB_CI_CLI_SKILLS_DIR env var > default relative to package
|
|
19
|
+
*/
|
|
20
|
+
function getSkillsDir() {
|
|
21
|
+
const envDir = process.env.GITLAB_CI_CLI_SKILLS_DIR;
|
|
22
|
+
if (envDir) {
|
|
23
|
+
return resolve(envDir);
|
|
24
|
+
}
|
|
25
|
+
// Default: ../../skill-data/ relative to this file's directory
|
|
26
|
+
return resolve(__dirname, '..', '..', 'skill-data');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Read and parse the manifest file.
|
|
30
|
+
*/
|
|
31
|
+
function readManifest() {
|
|
32
|
+
const manifestPath = join(getSkillsDir(), 'manifest.json');
|
|
33
|
+
if (!existsSync(manifestPath)) {
|
|
34
|
+
return { skills: [] };
|
|
35
|
+
}
|
|
36
|
+
const content = readFileSync(manifestPath, 'utf-8');
|
|
37
|
+
return JSON.parse(content);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the path to a skill's content directory.
|
|
41
|
+
*/
|
|
42
|
+
function getSkillPath(name) {
|
|
43
|
+
return join(getSkillsDir(), name);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if a skill exists.
|
|
47
|
+
*/
|
|
48
|
+
function skillExists(name) {
|
|
49
|
+
const skillPath = getSkillPath(name);
|
|
50
|
+
return existsSync(skillPath);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Read all content files for a skill, returning filename -> content mapping.
|
|
54
|
+
*/
|
|
55
|
+
function readSkillContent(name) {
|
|
56
|
+
const skillPath = getSkillPath(name);
|
|
57
|
+
const files = new Map();
|
|
58
|
+
if (!existsSync(skillPath))
|
|
59
|
+
return files;
|
|
60
|
+
const entries = readdirSync(skillPath, { withFileTypes: true });
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (entry.isFile()) {
|
|
63
|
+
const filePath = join(skillPath, entry.name);
|
|
64
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
65
|
+
files.set(entry.name, content);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return files;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* List all available skills sorted alphabetically.
|
|
72
|
+
*/
|
|
73
|
+
function listSkills() {
|
|
74
|
+
const manifest = readManifest();
|
|
75
|
+
return manifest.skills
|
|
76
|
+
.map((s) => ({
|
|
77
|
+
name: s.name,
|
|
78
|
+
description: s.description,
|
|
79
|
+
path: getSkillPath(s.name),
|
|
80
|
+
}))
|
|
81
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
82
|
+
}
|
|
83
|
+
// ──────────────────────────────────────────────
|
|
84
|
+
// Formatters
|
|
85
|
+
// ──────────────────────────────────────────────
|
|
86
|
+
function formatSkillList(skills) {
|
|
87
|
+
if (skills.length === 0) {
|
|
88
|
+
return 'No skills installed.';
|
|
89
|
+
}
|
|
90
|
+
const maxNameLen = Math.max(...skills.map((s) => s.name.length));
|
|
91
|
+
const lines = ['Available skills:'];
|
|
92
|
+
for (const skill of skills) {
|
|
93
|
+
const paddedName = skill.name.padEnd(maxNameLen + 2);
|
|
94
|
+
lines.push(` ${paddedName}${skill.description}`);
|
|
95
|
+
}
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
// ──────────────────────────────────────────────
|
|
99
|
+
// Handlers
|
|
100
|
+
// ──────────────────────────────────────────────
|
|
101
|
+
/**
|
|
102
|
+
* Handle `skills list [--json]`.
|
|
103
|
+
*/
|
|
104
|
+
export async function handleSkillsList(_config, options = {}) {
|
|
105
|
+
const skills = listSkills();
|
|
106
|
+
if (options.json) {
|
|
107
|
+
return {
|
|
108
|
+
exitCode: 0,
|
|
109
|
+
output: JSON.stringify(skills, null, 2),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
exitCode: 0,
|
|
114
|
+
output: formatSkillList(skills),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle `skills get <name> [--full]` or `skills get --all`.
|
|
119
|
+
*/
|
|
120
|
+
export async function handleSkillsGet(name, _config, options = {}) {
|
|
121
|
+
// --all mode: dump all skills
|
|
122
|
+
if (options.all) {
|
|
123
|
+
const skills = listSkills();
|
|
124
|
+
if (skills.length === 0) {
|
|
125
|
+
return { exitCode: 0, output: 'No skills installed.' };
|
|
126
|
+
}
|
|
127
|
+
const parts = [];
|
|
128
|
+
for (const skill of skills) {
|
|
129
|
+
const content = readSkillContent(skill.name);
|
|
130
|
+
const contentStr = formatSkillContent(skill.name, content, options.full ?? false);
|
|
131
|
+
parts.push(contentStr);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
exitCode: 0,
|
|
135
|
+
output: parts.join('\n\n---\n\n'),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Named skill
|
|
139
|
+
if (!name) {
|
|
140
|
+
return { exitCode: 1, output: 'No skill name specified. Use `skills get <name>` or `skills get --all`.' };
|
|
141
|
+
}
|
|
142
|
+
if (!skillExists(name)) {
|
|
143
|
+
const available = listSkills()
|
|
144
|
+
.map((s) => s.name)
|
|
145
|
+
.join(', ');
|
|
146
|
+
return {
|
|
147
|
+
exitCode: 1,
|
|
148
|
+
output: `Skill '${name}' not found. Available skills: ${available}`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const content = readSkillContent(name);
|
|
152
|
+
return {
|
|
153
|
+
exitCode: 0,
|
|
154
|
+
output: formatSkillContent(name, content, options.full ?? false),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Handle `skills path [name]`.
|
|
159
|
+
*/
|
|
160
|
+
export async function handleSkillsPath(name, _config, _options = {}) {
|
|
161
|
+
if (name) {
|
|
162
|
+
if (!skillExists(name)) {
|
|
163
|
+
return {
|
|
164
|
+
exitCode: 1,
|
|
165
|
+
output: `Skill '${name}' not found.`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
exitCode: 0,
|
|
170
|
+
output: getSkillPath(name),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
exitCode: 0,
|
|
175
|
+
output: getSkillsDir(),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// ──────────────────────────────────────────────
|
|
179
|
+
// Internal helpers
|
|
180
|
+
// ──────────────────────────────────────────────
|
|
181
|
+
/**
|
|
182
|
+
* Format skill content for display.
|
|
183
|
+
*/
|
|
184
|
+
function formatSkillContent(name, files, full) {
|
|
185
|
+
if (files.size === 0) {
|
|
186
|
+
return `Skill '${name}' has no content files.`;
|
|
187
|
+
}
|
|
188
|
+
const parts = [];
|
|
189
|
+
// In full mode, include all files
|
|
190
|
+
// In normal mode, skip reference/template files that are supplementary
|
|
191
|
+
for (const [filename, content] of files) {
|
|
192
|
+
// Skip supplementary files in non-full mode
|
|
193
|
+
if (!full && (filename === 'reference.md' || filename === 'templates.md')) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
parts.push(`--- ${filename} ---`);
|
|
197
|
+
parts.push(content.trimEnd());
|
|
198
|
+
}
|
|
199
|
+
// If nothing was included (all files skipped), fall back to including everything
|
|
200
|
+
if (parts.length === 0) {
|
|
201
|
+
for (const [filename, content] of files) {
|
|
202
|
+
parts.push(`--- ${filename} ---`);
|
|
203
|
+
parts.push(content.trimEnd());
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return parts.join('\n\n');
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline validation command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `validate` command with support for dry-run, project context,
|
|
5
|
+
* simulated variables, stdin input, and JSON output.
|
|
6
|
+
*/
|
|
7
|
+
import type { GitLabCIConfig } from '../config/types.js';
|
|
8
|
+
export interface ValidateOptions {
|
|
9
|
+
/** Read pipeline content from stdin instead of a file */
|
|
10
|
+
stdin?: boolean;
|
|
11
|
+
/** Enable dry-run mode for rules evaluation */
|
|
12
|
+
dryRun?: boolean;
|
|
13
|
+
/** Project path for context-aware validation */
|
|
14
|
+
project?: string;
|
|
15
|
+
/** Simulated CI/CD variables (KEY=VALUE strings) */
|
|
16
|
+
vars?: string[];
|
|
17
|
+
/** Output results as JSON */
|
|
18
|
+
json?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Handle `validate <file>` or `validate --stdin`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function handleValidate(filePath: string | undefined, config: Partial<GitLabCIConfig>, options?: ValidateOptions): Promise<{
|
|
24
|
+
exitCode: number;
|
|
25
|
+
output: string;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAiJD;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiF/C"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline validation command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `validate` command with support for dry-run, project context,
|
|
5
|
+
* simulated variables, stdin input, and JSON output.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { LintApi } from '../api/lint.js';
|
|
9
|
+
import { GitLabApiClient } from '../api/gitlab.js';
|
|
10
|
+
import { AuthenticationError, PermissionError } from '../types/api.js';
|
|
11
|
+
// ──────────────────────────────────────────────
|
|
12
|
+
// Helpers
|
|
13
|
+
// ──────────────────────────────────────────────
|
|
14
|
+
function createLintApi(config) {
|
|
15
|
+
const client = new GitLabApiClient(config);
|
|
16
|
+
return new LintApi(client);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Read content from stdin asynchronously.
|
|
20
|
+
*/
|
|
21
|
+
async function readStdin() {
|
|
22
|
+
const chunks = [];
|
|
23
|
+
for await (const chunk of process.stdin) {
|
|
24
|
+
chunks.push(Buffer.from(chunk));
|
|
25
|
+
}
|
|
26
|
+
return Buffer.concat(chunks).toString('utf-8');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse an array of "KEY=VALUE" strings into a record.
|
|
30
|
+
*/
|
|
31
|
+
function parseVars(vars) {
|
|
32
|
+
if (!vars || vars.length === 0)
|
|
33
|
+
return undefined;
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const v of vars) {
|
|
36
|
+
const eqIdx = v.indexOf('=');
|
|
37
|
+
if (eqIdx === -1)
|
|
38
|
+
continue; // skip malformed
|
|
39
|
+
const key = v.slice(0, eqIdx);
|
|
40
|
+
const value = v.slice(eqIdx + 1);
|
|
41
|
+
if (key)
|
|
42
|
+
result[key] = value;
|
|
43
|
+
}
|
|
44
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Format a validation result for text display.
|
|
48
|
+
*/
|
|
49
|
+
function formatTextResult(result, options) {
|
|
50
|
+
const lines = [];
|
|
51
|
+
// Title
|
|
52
|
+
const isValid = result.status === 'valid' && (result.valid ?? true);
|
|
53
|
+
if (isValid) {
|
|
54
|
+
lines.push('Pipeline configuration is valid');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
lines.push('Pipeline configuration is invalid');
|
|
58
|
+
}
|
|
59
|
+
// Show context
|
|
60
|
+
if (options.project) {
|
|
61
|
+
lines.push(`Project context: ${options.project}`);
|
|
62
|
+
}
|
|
63
|
+
if (options.dryRun) {
|
|
64
|
+
lines.push('Dry-run mode: rules evaluated');
|
|
65
|
+
}
|
|
66
|
+
if (options.vars && Object.keys(options.vars).length > 0) {
|
|
67
|
+
lines.push(`Simulated variables: ${Object.entries(options.vars)
|
|
68
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
69
|
+
.join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
// Errors
|
|
72
|
+
if (result.errors.length > 0) {
|
|
73
|
+
lines.push('');
|
|
74
|
+
lines.push('Errors:');
|
|
75
|
+
for (const err of result.errors) {
|
|
76
|
+
const loc = err.line ? `Line ${err.line}${err.column ? `, col ${err.column}` : ''}` : '';
|
|
77
|
+
lines.push(` ${loc ? `${loc}: ` : ''}${err.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Warnings
|
|
81
|
+
if (result.warnings.length > 0) {
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push('Warnings:');
|
|
84
|
+
for (const warn of result.warnings) {
|
|
85
|
+
const loc = warn.line ? `Line ${warn.line}${warn.column ? `, col ${warn.column}` : ''}` : '';
|
|
86
|
+
lines.push(` ${loc ? `${loc}: ` : ''}${warn.message}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Jobs (dry-run or includeJobs)
|
|
90
|
+
if (result.jobs && result.jobs.length > 0) {
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push('Jobs:');
|
|
93
|
+
for (const job of result.jobs) {
|
|
94
|
+
const willRun = job.when !== 'never' && job.when !== 'manual';
|
|
95
|
+
const icon = willRun ? '✅' : '❌';
|
|
96
|
+
const reason = job.except_reason ? ` (${job.except_reason})` : '';
|
|
97
|
+
lines.push(` ${icon} ${job.name} stage: ${job.stage}${reason}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return lines.join('\n');
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Format a validation result as JSON.
|
|
104
|
+
*/
|
|
105
|
+
function formatJsonResult(result, options) {
|
|
106
|
+
return JSON.stringify({
|
|
107
|
+
success: result.status === 'valid',
|
|
108
|
+
status: result.status,
|
|
109
|
+
errors: result.errors,
|
|
110
|
+
warnings: result.warnings,
|
|
111
|
+
jobs: result.jobs,
|
|
112
|
+
context: {
|
|
113
|
+
project: options.project ?? null,
|
|
114
|
+
dryRun: options.dryRun ?? false,
|
|
115
|
+
vars: options.vars ?? null,
|
|
116
|
+
},
|
|
117
|
+
}, null, 2);
|
|
118
|
+
}
|
|
119
|
+
// ──────────────────────────────────────────────
|
|
120
|
+
// Handlers
|
|
121
|
+
// ──────────────────────────────────────────────
|
|
122
|
+
/**
|
|
123
|
+
* Handle `validate <file>` or `validate --stdin`.
|
|
124
|
+
*/
|
|
125
|
+
export async function handleValidate(filePath, config, options = {}) {
|
|
126
|
+
try {
|
|
127
|
+
// ── Read pipeline content ──────────────────
|
|
128
|
+
let content;
|
|
129
|
+
if (options.stdin) {
|
|
130
|
+
content = await readStdin();
|
|
131
|
+
}
|
|
132
|
+
else if (filePath) {
|
|
133
|
+
try {
|
|
134
|
+
content = readFileSync(filePath, 'utf-8');
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return {
|
|
138
|
+
exitCode: 1,
|
|
139
|
+
output: options.json
|
|
140
|
+
? JSON.stringify({ success: false, error: { message: `File '${filePath}' not found` } })
|
|
141
|
+
: `File '${filePath}' not found`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return {
|
|
147
|
+
exitCode: 1,
|
|
148
|
+
output: options.json
|
|
149
|
+
? JSON.stringify({ success: false, error: { message: 'No input provided. Specify a file or use --stdin.' } })
|
|
150
|
+
: 'No input provided. Specify a file or use --stdin.',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// ── Build API options ──────────────────────
|
|
154
|
+
const variables = parseVars(options.vars);
|
|
155
|
+
const api = createLintApi(config);
|
|
156
|
+
const result = await api.validate(content, {
|
|
157
|
+
project: options.project,
|
|
158
|
+
dryRun: options.dryRun,
|
|
159
|
+
variables,
|
|
160
|
+
includeJobs: options.dryRun, // include jobs when dry-run
|
|
161
|
+
});
|
|
162
|
+
// ── Format output ──────────────────────────
|
|
163
|
+
const formatOptions = {
|
|
164
|
+
dryRun: options.dryRun,
|
|
165
|
+
vars: variables,
|
|
166
|
+
project: options.project,
|
|
167
|
+
};
|
|
168
|
+
const output = options.json
|
|
169
|
+
? formatJsonResult(result, formatOptions)
|
|
170
|
+
: formatTextResult(result, formatOptions);
|
|
171
|
+
// Exit code: 0 if valid, non-zero if invalid
|
|
172
|
+
const exitCode = result.status === 'valid' && (result.valid ?? true) ? 0 : 1;
|
|
173
|
+
return { exitCode, output };
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
177
|
+
// Handle permission errors gracefully
|
|
178
|
+
if (err instanceof AuthenticationError || err instanceof PermissionError) {
|
|
179
|
+
const userMessage = options.project
|
|
180
|
+
? `Insufficient permissions to access project '${options.project}'`
|
|
181
|
+
: `Authentication failed: ${message}`;
|
|
182
|
+
if (options.json) {
|
|
183
|
+
return {
|
|
184
|
+
exitCode: 1,
|
|
185
|
+
output: JSON.stringify({ success: false, error: { message: userMessage } }),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return { exitCode: 1, output: userMessage };
|
|
189
|
+
}
|
|
190
|
+
// Generic error
|
|
191
|
+
const userMessage = `Error: ${message}`;
|
|
192
|
+
if (options.json) {
|
|
193
|
+
return {
|
|
194
|
+
exitCode: 1,
|
|
195
|
+
output: JSON.stringify({ success: false, error: { message: userMessage } }),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { exitCode: 1, output: userMessage };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAmBvE,iDAAiD;AACjD,UAAU;AACV,iDAAiD;AAEjD,SAAS,aAAa,CAAC,MAA+B;IACpD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,SAAS;IACtB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,IAA0B;IAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEjD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,SAAS,CAAC,iBAAiB;QAC7C,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACjC,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/B,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAYD;;GAEG;AACH,SAAS,gBAAgB,CACvB,MAA2C,EAC3C,OAAsB;IAEtB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,QAAQ;IACR,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IACpE,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAClD,CAAC;IAED,eAAe;IACf,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CACR,wBAAwB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;aACjD,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;aAC5B,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzF,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,WAAW;IACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7F,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;YAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACjC,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,YAAY,GAAG,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,MAA2C,EAC3C,OAAsB;IAEtB,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,OAAO;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE;YACP,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;SAC3B;KACF,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,WAAW;AACX,iDAAiD;AAEjD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAA4B,EAC5B,MAA+B,EAC/B,UAA2B,EAAE;IAE7B,IAAI,CAAC;QACH,8CAA8C;QAC9C,IAAI,OAAe,CAAC;QACpB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;oBACL,QAAQ,EAAE,CAAC;oBACX,MAAM,EAAE,OAAO,CAAC,IAAI;wBAClB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,QAAQ,aAAa,EAAE,EAAE,CAAC;wBACxF,CAAC,CAAC,SAAS,QAAQ,aAAa;iBACnC,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE,OAAO,CAAC,IAAI;oBAClB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,mDAAmD,EAAE,EAAE,CAAC;oBAC7G,CAAC,CAAC,mDAAmD;aACxD,CAAC;QACJ,CAAC;QAED,8CAA8C;QAC9C,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE;YACzC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS;YACT,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,4BAA4B;SAC1D,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,aAAa,GAAkB;YACnC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;QAEF,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI;YACzB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC;YACzC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAE5C,6CAA6C;QAC7C,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEjE,sCAAsC;QACtC,IAAI,GAAG,YAAY,mBAAmB,IAAI,GAAG,YAAY,eAAe,EAAE,CAAC;YACzE,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO;gBACjC,CAAC,CAAC,+CAA+C,OAAO,CAAC,OAAO,GAAG;gBACnE,CAAC,CAAC,0BAA0B,OAAO,EAAE,CAAC;YAExC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO;oBACL,QAAQ,EAAE,CAAC;oBACX,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC;iBAC5E,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAC9C,CAAC;QAED,gBAAgB;QAChB,MAAM,WAAW,GAAG,UAAU,OAAO,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO;gBACL,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC;aAC5E,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC9C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for gitlab-ci-cli.
|
|
3
|
+
*
|
|
4
|
+
* Loads configuration from multiple sources with proper precedence:
|
|
5
|
+
* 1. User config file (~/.gitlab-ci-cli.json) — lowest priority
|
|
6
|
+
* 2. Project config file (./.gitlab-ci-cli.json) — overrides user
|
|
7
|
+
* 3. Environment variables (GITLAB_CI_CLI_*) — overrides files
|
|
8
|
+
* 4. CLI flags — highest priority
|
|
9
|
+
*/
|
|
10
|
+
import { type GitLabCIConfig, type ResolvedConfig, type RawConfigFile } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Known config keys (including optional ones like `token`, `project`).
|
|
13
|
+
* Used to check key membership instead of `in config` since optional
|
|
14
|
+
* keys may not be present in the default config object.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CONFIG_KEYS: Array<keyof GitLabCIConfig>;
|
|
17
|
+
/**
|
|
18
|
+
* Read and parse a JSON config file.
|
|
19
|
+
* Returns null if the file doesn't exist.
|
|
20
|
+
* Returns a string error message prefixed with 'ERROR:' if the JSON is invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare function readConfigFile(filePath: string): RawConfigFile | null | string;
|
|
23
|
+
/**
|
|
24
|
+
* Find and load a config file for the given directory.
|
|
25
|
+
* Returns null if no config file exists.
|
|
26
|
+
* Returns a warning string prefixed with 'ERROR:' if invalid JSON.
|
|
27
|
+
*/
|
|
28
|
+
export declare function loadProjectConfig(startDir?: string): RawConfigFile | null | string;
|
|
29
|
+
/**
|
|
30
|
+
* Load the user-level config file from the home directory.
|
|
31
|
+
* Returns null if no config file exists.
|
|
32
|
+
* Returns a warning string prefixed with 'ERROR:' if invalid JSON.
|
|
33
|
+
*/
|
|
34
|
+
export declare function loadUserConfig(): RawConfigFile | null | string;
|
|
35
|
+
/**
|
|
36
|
+
* Load both user and project config files.
|
|
37
|
+
* Returns [userConfig, projectConfig] where each may be null or an error string.
|
|
38
|
+
*/
|
|
39
|
+
export declare function loadConfigFiles(): {
|
|
40
|
+
user: RawConfigFile | null | string;
|
|
41
|
+
project: RawConfigFile | null | string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Merge two config objects.
|
|
45
|
+
* Project-level values override user-level values.
|
|
46
|
+
*/
|
|
47
|
+
export declare function mergeConfigs(base: Partial<GitLabCIConfig>, override: Partial<GitLabCIConfig>): Partial<GitLabCIConfig>;
|
|
48
|
+
/**
|
|
49
|
+
* Read environment variables and apply overrides.
|
|
50
|
+
* Returns a partial config with only the env-overridden keys.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readEnvOverrides(): {
|
|
53
|
+
overrides: Partial<GitLabCIConfig>;
|
|
54
|
+
warnings: string[];
|
|
55
|
+
};
|
|
56
|
+
export interface CliFlagOverrides {
|
|
57
|
+
gitlabUrl?: string;
|
|
58
|
+
token?: string;
|
|
59
|
+
project?: string;
|
|
60
|
+
timeout?: number;
|
|
61
|
+
output?: 'table' | 'json';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build the full configuration by applying the precedence chain:
|
|
65
|
+
* 1. Start with defaults
|
|
66
|
+
* 2. Overlay user config file
|
|
67
|
+
* 3. Overlay project config file
|
|
68
|
+
* 4. Overlay environment variables
|
|
69
|
+
* 5. Overlay CLI flags
|
|
70
|
+
*
|
|
71
|
+
* Returns a ResolvedConfig with source tracking and warnings.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getConfig(cliFlags?: CliFlagOverrides): ResolvedConfig;
|
|
74
|
+
/**
|
|
75
|
+
* Quick access to the resolved config for cases where
|
|
76
|
+
* full ResolvedConfig tracking is not needed.
|
|
77
|
+
* Wraps getConfig() and returns just the config object.
|
|
78
|
+
*/
|
|
79
|
+
export declare function loadConfig(cliFlags?: CliFlagOverrides): GitLabCIConfig;
|
|
80
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAGnB,MAAM,YAAY,CAAC;AAQpB;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,MAAM,cAAc,CAMnD,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,GAAG,MAAM,CAc9E;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,MAAsB,GAAG,aAAa,GAAG,IAAI,GAAG,MAAM,CAGjG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,aAAa,GAAG,IAAI,GAAG,MAAM,CAG9D;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI;IAAE,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAAA;CAAE,CAKjH;AAMD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,EAC7B,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC,CAEzB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI;IAClC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAmBA;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAMD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAuErE;AAMD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAEtE"}
|