@lightdash/cli 0.2638.1 → 0.2639.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.
@@ -5,6 +5,7 @@ type InstallSkillsOptions = {
5
5
  global: boolean;
6
6
  path?: string;
7
7
  };
8
+ export declare function getVersionWithSkills(): string;
8
9
  export declare const installSkillsHandler: (options: InstallSkillsOptions) => Promise<void>;
9
10
  export {};
10
11
  //# sourceMappingURL=installSkills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"installSkills.d.ts","sourceRoot":"","sources":["../../src/handlers/installSkills.ts"],"names":[],"mappings":"AAaA,KAAK,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/C,KAAK,oBAAoB,GAAG;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAuMF,eAAO,MAAM,oBAAoB,GAC7B,SAAS,oBAAoB,KAC9B,OAAO,CAAC,IAAI,CA0Ed,CAAC"}
1
+ {"version":3,"file":"installSkills.d.ts","sourceRoot":"","sources":["../../src/handlers/installSkills.ts"],"names":[],"mappings":"AAgBA,KAAK,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/C,KAAK,oBAAoB,GAAG;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AA8SF,wBAAgB,oBAAoB,IAAI,MAAM,CA8B7C;AAED,eAAO,MAAM,oBAAoB,GAC7B,SAAS,oBAAoB,KAC9B,OAAO,CAAC,IAAI,CA8Ed,CAAC"}
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.installSkillsHandler = void 0;
4
+ exports.getVersionWithSkills = getVersionWithSkills;
4
5
  const tslib_1 = require("tslib");
5
6
  const fs = tslib_1.__importStar(require("fs"));
6
7
  const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
7
8
  const os = tslib_1.__importStar(require("os"));
8
9
  const path = tslib_1.__importStar(require("path"));
9
10
  const analytics_1 = require("../analytics/analytics");
11
+ const env_1 = require("../env");
10
12
  const globalState_1 = tslib_1.__importDefault(require("../globalState"));
11
13
  const styles = tslib_1.__importStar(require("../styles"));
14
+ const SKILL_MANIFEST_FILENAME = '.lightdash-skill-manifest.json';
12
15
  const GITHUB_API_BASE = 'https://api.github.com/repos/lightdash/lightdash/contents';
13
- const GITHUB_RAW_BASE = 'https://raw.githubusercontent.com/lightdash/lightdash/main';
16
+ const GITHUB_RAW_BASE = `https://raw.githubusercontent.com/lightdash/lightdash/${env_1.CLI_VERSION}`;
14
17
  function getAgentSkillsDir(agent) {
15
18
  switch (agent) {
16
19
  case 'claude':
@@ -59,7 +62,7 @@ function getInstallPath(options) {
59
62
  return path.join(cwd, skillsDir);
60
63
  }
61
64
  async function fetchGitHubDirectory(repoPath) {
62
- const url = `${GITHUB_API_BASE}/${repoPath}`;
65
+ const url = `${GITHUB_API_BASE}/${repoPath}?ref=${env_1.CLI_VERSION}`;
63
66
  globalState_1.default.debug(`> Fetching GitHub directory: ${url}`);
64
67
  const response = await (0, node_fetch_1.default)(url, {
65
68
  headers: {
@@ -88,6 +91,9 @@ function resolveSymlinkTarget(symlinkPath, target) {
88
91
  const symlinkDir = path.posix.dirname(symlinkPath);
89
92
  return path.posix.normalize(path.posix.join(symlinkDir, target.trim()));
90
93
  }
94
+ function interpolateVersionPlaceholders(content) {
95
+ return content.replace(/\{\{CLI_VERSION\}\}/g, env_1.CLI_VERSION);
96
+ }
91
97
  /* eslint-disable no-await-in-loop */
92
98
  // Sequential downloads are intentional to avoid GitHub rate limits and handle symlinks
93
99
  async function downloadSkillFiles(repoPath, localDir, visited = new Set()) {
@@ -121,7 +127,7 @@ async function downloadSkillFiles(repoPath, localDir, visited = new Set()) {
121
127
  }
122
128
  else if (targetItem.download_url) {
123
129
  const content = await fetchFileContent(targetItem.download_url);
124
- fs.writeFileSync(targetLocalPath, content);
130
+ fs.writeFileSync(targetLocalPath, interpolateVersionPlaceholders(content));
125
131
  }
126
132
  }
127
133
  }
@@ -131,7 +137,7 @@ async function downloadSkillFiles(repoPath, localDir, visited = new Set()) {
131
137
  const content = await fetchFileContent(downloadUrl);
132
138
  // Ensure parent directory exists
133
139
  fs.mkdirSync(path.dirname(localPath), { recursive: true });
134
- fs.writeFileSync(localPath, content);
140
+ fs.writeFileSync(localPath, interpolateVersionPlaceholders(content));
135
141
  }
136
142
  }
137
143
  else if (item.type === 'file' && item.download_url) {
@@ -143,7 +149,7 @@ async function downloadSkillFiles(repoPath, localDir, visited = new Set()) {
143
149
  content = await fetchFileContent(`${GITHUB_RAW_BASE}/${resolvedPath}`);
144
150
  }
145
151
  fs.mkdirSync(path.dirname(localPath), { recursive: true });
146
- fs.writeFileSync(localPath, content);
152
+ fs.writeFileSync(localPath, interpolateVersionPlaceholders(content));
147
153
  }
148
154
  }
149
155
  }
@@ -152,6 +158,95 @@ async function listAvailableSkills() {
152
158
  const items = await fetchGitHubDirectory('skills');
153
159
  return items.filter((item) => item.type === 'dir').map((item) => item.name);
154
160
  }
161
+ function writeSkillManifest(skillDir) {
162
+ const manifest = {
163
+ version: env_1.CLI_VERSION,
164
+ installed_at: new Date().toISOString(),
165
+ };
166
+ fs.writeFileSync(path.join(skillDir, SKILL_MANIFEST_FILENAME), JSON.stringify(manifest, null, 2));
167
+ }
168
+ function readSkillManifest(skillDir) {
169
+ const manifestPath = path.join(skillDir, SKILL_MANIFEST_FILENAME);
170
+ if (!fs.existsSync(manifestPath)) {
171
+ return null;
172
+ }
173
+ try {
174
+ return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
175
+ }
176
+ catch {
177
+ return null;
178
+ }
179
+ }
180
+ function findInstalledSkills() {
181
+ const agents = ['claude', 'cursor', 'codex'];
182
+ const results = [];
183
+ const roots = [
184
+ { path: os.homedir(), scope: 'global' },
185
+ ];
186
+ const cwd = process.cwd();
187
+ const gitRoot = findGitRoot(cwd);
188
+ roots.push({ path: gitRoot || cwd, scope: 'project' });
189
+ for (const root of roots) {
190
+ for (const agent of agents) {
191
+ const skillsDir = path.join(root.path, getAgentSkillsDir(agent));
192
+ if (!fs.existsSync(skillsDir)) {
193
+ // eslint-disable-next-line no-continue
194
+ continue;
195
+ }
196
+ let entries;
197
+ try {
198
+ entries = fs.readdirSync(skillsDir);
199
+ }
200
+ catch {
201
+ // eslint-disable-next-line no-continue
202
+ continue;
203
+ }
204
+ entries
205
+ .filter((e) => fs.statSync(path.join(skillsDir, e)).isDirectory())
206
+ .forEach((entry) => {
207
+ const manifest = readSkillManifest(path.join(skillsDir, entry));
208
+ if (manifest) {
209
+ results.push({
210
+ name: entry,
211
+ version: manifest.version,
212
+ agent,
213
+ scope: root.scope,
214
+ isOutdated: manifest.version !== env_1.CLI_VERSION,
215
+ });
216
+ }
217
+ });
218
+ }
219
+ }
220
+ return results;
221
+ }
222
+ function getVersionWithSkills() {
223
+ const lines = [env_1.CLI_VERSION];
224
+ const skills = findInstalledSkills();
225
+ if (skills.length > 0) {
226
+ lines.push('');
227
+ lines.push('Installed skills:');
228
+ for (const skill of skills) {
229
+ const line = ` ${skill.name} v${skill.version} [${skill.agent}, ${skill.scope}]`;
230
+ lines.push(skill.isOutdated ? styles.warning(line) : line);
231
+ }
232
+ const outdated = skills.filter((s) => s.isOutdated);
233
+ if (outdated.length > 0) {
234
+ lines.push('');
235
+ lines.push(styles.warning('Update with:'));
236
+ const seen = new Set();
237
+ for (const skill of outdated) {
238
+ const globalFlag = skill.scope === 'global' ? ' --global' : '';
239
+ const agentFlag = ` --agent ${skill.agent}`;
240
+ const cmd = `lightdash install-skills${globalFlag}${agentFlag}`;
241
+ if (!seen.has(cmd)) {
242
+ seen.add(cmd);
243
+ lines.push(styles.warning(` ${cmd}`));
244
+ }
245
+ }
246
+ }
247
+ }
248
+ return lines.join('\n');
249
+ }
155
250
  const installSkillsHandler = async (options) => {
156
251
  const startTime = Date.now();
157
252
  let success = true;
@@ -160,6 +255,7 @@ const installSkillsHandler = async (options) => {
160
255
  console.error(styles.title('\n⚡ Lightdash Skills Installer\n'));
161
256
  console.error(`Agent: ${styles.bold(options.agent)}`);
162
257
  console.error(`Scope: ${styles.bold(options.global ? 'global' : 'project')}`);
258
+ console.error(`Version: ${styles.bold(env_1.CLI_VERSION)}`);
163
259
  console.error(`Install path: ${styles.bold(installPath)}\n`);
164
260
  const spinner = globalState_1.default.startSpinner('Fetching available skills...');
165
261
  try {
@@ -184,7 +280,8 @@ const installSkillsHandler = async (options) => {
184
280
  }
185
281
  fs.mkdirSync(skillLocalPath, { recursive: true });
186
282
  await downloadSkillFiles(`skills/${skill}`, skillLocalPath);
187
- skillSpinner.succeed(`Installed skill: ${skill}`);
283
+ writeSkillManifest(skillLocalPath);
284
+ skillSpinner.succeed(`Installed skill: ${skill} (v${env_1.CLI_VERSION})`);
188
285
  }
189
286
  catch (err) {
190
287
  const errorMessage = err instanceof Error ? err.message : String(err);
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ function parseProjectArgument(value) {
68
68
  return value;
69
69
  }
70
70
  commander_1.program
71
- .version(env_1.CLI_VERSION)
71
+ .version((0, installSkills_1.getVersionWithSkills)())
72
72
  .name(styles.title('⚡️lightdash'))
73
73
  .description('Developer tools for dbt and Lightdash.\nSee https://docs.lightdash.com for more help and examples')
74
74
  .option('--non-interactive', 'Disable all interactive prompts. Commands fail with helpful error if required input is missing.')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "0.2638.1",
3
+ "version": "0.2639.1",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,8 +40,8 @@
40
40
  "unique-names-generator": "^4.7.1",
41
41
  "uuid": "^11.0.3",
42
42
  "yaml": "^2.7.0",
43
- "@lightdash/common": "0.2638.1",
44
- "@lightdash/warehouses": "0.2638.1"
43
+ "@lightdash/warehouses": "0.2639.1",
44
+ "@lightdash/common": "0.2639.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/inquirer": "^8.2.1",