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.
Files changed (80) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +75 -0
  3. package/bin/gitlab-ci-cli.js +29 -0
  4. package/dist/api/catalog.d.ts +38 -0
  5. package/dist/api/catalog.d.ts.map +1 -0
  6. package/dist/api/catalog.js +72 -0
  7. package/dist/api/catalog.js.map +1 -0
  8. package/dist/api/gitlab.d.ts +69 -0
  9. package/dist/api/gitlab.d.ts.map +1 -0
  10. package/dist/api/gitlab.js +226 -0
  11. package/dist/api/gitlab.js.map +1 -0
  12. package/dist/api/lint.d.ts +61 -0
  13. package/dist/api/lint.d.ts.map +1 -0
  14. package/dist/api/lint.js +41 -0
  15. package/dist/api/lint.js.map +1 -0
  16. package/dist/cache/schema-cache.d.ts +54 -0
  17. package/dist/cache/schema-cache.d.ts.map +1 -0
  18. package/dist/cache/schema-cache.js +124 -0
  19. package/dist/cache/schema-cache.js.map +1 -0
  20. package/dist/commands/batch.d.ts +19 -0
  21. package/dist/commands/batch.d.ts.map +1 -0
  22. package/dist/commands/batch.js +174 -0
  23. package/dist/commands/batch.js.map +1 -0
  24. package/dist/commands/catalog.d.ts +42 -0
  25. package/dist/commands/catalog.d.ts.map +1 -0
  26. package/dist/commands/catalog.js +158 -0
  27. package/dist/commands/catalog.js.map +1 -0
  28. package/dist/commands/component.d.ts +46 -0
  29. package/dist/commands/component.d.ts.map +1 -0
  30. package/dist/commands/component.js +213 -0
  31. package/dist/commands/component.js.map +1 -0
  32. package/dist/commands/pipeline.d.ts +61 -0
  33. package/dist/commands/pipeline.d.ts.map +1 -0
  34. package/dist/commands/pipeline.js +880 -0
  35. package/dist/commands/pipeline.js.map +1 -0
  36. package/dist/commands/setup.d.ts +119 -0
  37. package/dist/commands/setup.d.ts.map +1 -0
  38. package/dist/commands/setup.js +391 -0
  39. package/dist/commands/setup.js.map +1 -0
  40. package/dist/commands/skills.d.ts +39 -0
  41. package/dist/commands/skills.d.ts.map +1 -0
  42. package/dist/commands/skills.js +208 -0
  43. package/dist/commands/skills.js.map +1 -0
  44. package/dist/commands/validate.d.ts +27 -0
  45. package/dist/commands/validate.d.ts.map +1 -0
  46. package/dist/commands/validate.js +201 -0
  47. package/dist/commands/validate.js.map +1 -0
  48. package/dist/config/loader.d.ts +80 -0
  49. package/dist/config/loader.d.ts.map +1 -0
  50. package/dist/config/loader.js +217 -0
  51. package/dist/config/loader.js.map +1 -0
  52. package/dist/config/types.d.ts +46 -0
  53. package/dist/config/types.d.ts.map +1 -0
  54. package/dist/config/types.js +45 -0
  55. package/dist/config/types.js.map +1 -0
  56. package/dist/index.d.ts +10 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +437 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/output/table.d.ts +28 -0
  61. package/dist/output/table.d.ts.map +1 -0
  62. package/dist/output/table.js +67 -0
  63. package/dist/output/table.js.map +1 -0
  64. package/dist/types/api.d.ts +66 -0
  65. package/dist/types/api.d.ts.map +1 -0
  66. package/dist/types/api.js +61 -0
  67. package/dist/types/api.js.map +1 -0
  68. package/dist/types/catalog.d.ts +77 -0
  69. package/dist/types/catalog.d.ts.map +1 -0
  70. package/dist/types/catalog.js +5 -0
  71. package/dist/types/catalog.js.map +1 -0
  72. package/package.json +60 -0
  73. package/skill-data/core/reference.md +127 -0
  74. package/skill-data/core/templates.md +97 -0
  75. package/skill-data/core/workflows.md +84 -0
  76. package/skill-data/manifest.json +12 -0
  77. package/skill-data/templates/basic-pipeline.yml +29 -0
  78. package/skill-data/templates/docker-build.yml +38 -0
  79. package/skill-data/templates/multi-stage.yml +43 -0
  80. 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":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAwBzC,iDAAiD;AACjD,kBAAkB;AAClB,iDAAiD;AAEjD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;GAGG;AACH,SAAS,YAAY;IACnB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IACpD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,+DAA+D;IAC/D,OAAO,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAS,YAAY;IACnB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAEzC,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,UAAU;IACjB,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC,MAAM;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,iDAAiD;AACjD,aAAa;AACb,iDAAiD;AAEjD,SAAS,eAAe,CACtB,MAAkE;IAElE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,MAAM,KAAK,GAAa,CAAC,mBAAmB,CAAC,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,iDAAiD;AACjD,WAAW;AACX,iDAAiD;AAEjD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgC,EAChC,UAAuB,EAAE;IAEzB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;KAChC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAwB,EACxB,OAAgC,EAChC,UAAsB,EAAE;IAExB,8BAA8B;IAC9B,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;YAClF,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;SAClC,CAAC;IACJ,CAAC;IAED,cAAc;IACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,yEAAyE,EAAE,CAAC;IAC5G,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,UAAU,EAAE;aAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,UAAU,IAAI,kCAAkC,SAAS,EAAE;SACpE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC;KACjE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAwB,EACxB,OAAgC,EAChC,WAAwB,EAAE;IAE1B,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE,UAAU,IAAI,cAAc;aACrC,CAAC;QACJ,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC;SAC3B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,YAAY,EAAE;KACvB,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,mBAAmB;AACnB,iDAAiD;AAEjD;;GAEG;AACH,SAAS,kBAAkB,CACzB,IAAY,EACZ,KAA0B,EAC1B,IAAa;IAEb,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,UAAU,IAAI,yBAAyB,CAAC;IACjD,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,kCAAkC;IAClC,uEAAuE;IACvE,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;QACxC,4CAA4C;QAC5C,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,cAAc,IAAI,QAAQ,KAAK,cAAc,CAAC,EAAE,CAAC;YAC1E,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,MAAM,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,iFAAiF;IACjF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,MAAM,CAAC,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
@@ -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"}