@lightdash/cli 2.163.1 → 2.163.2

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.
@@ -124,14 +124,11 @@ export type AppDownloadErrorOutcome = {
124
124
  */
125
125
  export declare const classifyAppDownloadError: (err: unknown) => AppDownloadErrorOutcome;
126
126
  /**
127
- * Sums changes entries that represent actual upserts — excluding both
128
- * 'skipped' and 'failed' keys so that failures don't suppress the
129
- * "all content was skipped" warning.
127
+ * Sums changes entries that represent actual upserts, excluding skips and failures.
130
128
  */
131
129
  export declare const computeUpsertedTotal: (changes: Record<string, number>) => number;
132
130
  /**
133
- * Returns true when there is at least one skipped item and zero upserted
134
- * items — the condition that should display the "all skipped" warning.
131
+ * Show the --force hint only for unchanged content, not bundle skips or failures.
135
132
  */
136
133
  export declare const shouldWarnAllSkipped: (changes: Record<string, number>) => boolean;
137
134
  export declare const appsDownloadSummary: (successCount: number, total: number, failures: AppDownloadFailure[], appsDir: string, skippedNotBuiltCount: number, noun?: string) => {
@@ -1 +1 @@
1
- {"version":3,"file":"appsDownload.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/appsDownload.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"appsDownload.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/appsDownload.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAc3B,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,eAAO,MAAM,mBAAmB,cAAe,MAAM,KAAG,MAoBvD,CAAC;AAEF,eAAO,MAAM,sBAAsB,eACnB,MAAM,EAAE,eACP,OAAO,KACrB,GAAG,CAAC,MAAM,CAAC,GAAG,IACoD,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,WACpB,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,YAChB,eAAe,KAC1B,OAG2D,CAAC;AAE/D,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,WAClB,GAAG,CAAC,MAAM,CAAC,YACT,eAAe,KAC1B,MAAM,EAGJ,CAAC;AAEN;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QACvB,MAAM,UACH;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,KACzC,MAWF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,WACzB,GAAG,CAAC,MAAM,CAAC,cACP;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KACjD,GAAG,CAAC,MAAM,CAcZ,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,cACxB,MAAM,EAAE,SACb,MAAM,KACb,MAAM,GAAG,IAMX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,WAAY,MAAM,KAAG,MAC6K,CAAC;AAEjO;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aACf,MAAM,GAAG,SAAS,eACf,OAAO,cACT;IACP,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACpB,KAKF;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAejD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,QAAS,OAAO,KAAG,OACP,CAAC;AAE5D,MAAM,MAAM,qBAAqB,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,YAAa;IAC1C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,KAAG,qBASH,CAAC;AAEF,eAAO,MAAM,aAAa,gBACT,MAAM,EAAE,SACd,MAAM,KACd;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAG7C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,SAAU;IACxC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC/B,KAAG,MAAM,EAOT,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,WAC3B,MAAM,QACR,mBAAmB,KAC1B,mBASF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,SAAU;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,KAAG,MAKqD,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,uBAAuB,GAC7B;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,QAC5B,OAAO,KACb,uBAoBF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,YAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAGpB,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,oBAAoB,YACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAChC,OAgBF,CAAC;AAEF,eAAO,MAAM,mBAAmB,iBACd,MAAM,SACb,MAAM,YACH,kBAAkB,EAAE,WACrB,MAAM,wBACO,MAAM,SACtB,MAAM,KACb;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAiBxD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAClC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SAAgB;IAC1C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,KACb,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAIlC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1D,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D,KAAG,OAAO,CAAC,mBAAmB,CA0G9B,CAAC"}
@@ -198,19 +198,22 @@ const classifyAppDownloadError = (err) => {
198
198
  };
199
199
  exports.classifyAppDownloadError = classifyAppDownloadError;
200
200
  /**
201
- * Sums changes entries that represent actual upserts — excluding both
202
- * 'skipped' and 'failed' keys so that failures don't suppress the
203
- * "all content was skipped" warning.
201
+ * Sums changes entries that represent actual upserts, excluding skips and failures.
204
202
  */
205
203
  const computeUpsertedTotal = (changes) => Object.entries(changes)
206
204
  .filter(([key]) => !key.includes('skipped') && !key.includes('failed'))
207
205
  .reduce((sum, [, value]) => sum + value, 0);
208
206
  exports.computeUpsertedTotal = computeUpsertedTotal;
209
207
  /**
210
- * Returns true when there is at least one skipped item and zero upserted
211
- * items — the condition that should display the "all skipped" warning.
208
+ * Show the --force hint only for unchanged content, not bundle skips or failures.
212
209
  */
213
210
  const shouldWarnAllSkipped = (changes) => {
211
+ if (Object.entries(changes).some(([key, value]) => value > 0 &&
212
+ (key.includes('failed') ||
213
+ key === 'data apps skipped' ||
214
+ key === 'chart types skipped'))) {
215
+ return false;
216
+ }
214
217
  const totalSkipped = Object.entries(changes)
215
218
  .filter(([key]) => key.includes('skipped'))
216
219
  .reduce((sum, [, value]) => sum + value, 0);
@@ -363,6 +363,10 @@ describe('computeUpsertedTotal', () => {
363
363
  });
364
364
  });
365
365
  describe('shouldWarnAllSkipped', () => {
366
+ it.each(['data apps skipped', 'chart types skipped', 'data apps failed'])('does not suggest --force for %s, even with unchanged charts', (key) => {
367
+ expect((0, appsDownload_1.shouldWarnAllSkipped)({ [key]: 1 })).toBe(false);
368
+ expect((0, appsDownload_1.shouldWarnAllSkipped)({ [key]: 1, 'charts skipped': 3 })).toBe(false);
369
+ });
366
370
  it('returns true when everything was skipped', () => {
367
371
  expect((0, appsDownload_1.shouldWarnAllSkipped)({ 'charts skipped': 3 })).toBe(true);
368
372
  });
@@ -1 +1 @@
1
- {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAQH,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAC;AAwB3B,MAAM,MAAM,uBAAuB,GAAG;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,6BAA6B,EAAE,gBA4B3C,CAAC;AAEF,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,iBAAiB,YAC1B,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,OAAO,EACP,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,OAAO,EACP,aAAa,EACb,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,OAAO,EACP,UAAU,EACV,WAAW,CACL,CAAC;AAEX,eAAO,MAAM,mBAAmB,SACtB,MAAM,iBACG,MAAM,KACtB,MAWF,CAAC;AAEF,eAAO,MAAM,qBAAqB,SAAU;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,KAAG,eAaF,CAAC;AAqLH,eAAO,MAAM,gBAAgB,SACnB,MAAM,WACH,uBAAuB,KACjC,OAAO,CAAC,IAAI,CAoId,CAAC"}
1
+ {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAQH,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAC;AAwB3B,MAAM,MAAM,uBAAuB,GAAG;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,6BAA6B,EAAE,gBA4B3C,CAAC;AAEF,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,iBAAiB,YAC1B,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,OAAO,EACP,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,OAAO,EACP,aAAa,EACb,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,OAAO,EACP,UAAU,EACV,WAAW,CACL,CAAC;AAEX,eAAO,MAAM,mBAAmB,SACtB,MAAM,iBACG,MAAM,KACtB,MAWF,CAAC;AAEF,eAAO,MAAM,qBAAqB,SAAU;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,KAAG,eAaF,CAAC;AAqLH,eAAO,MAAM,gBAAgB,SACnB,MAAM,WACH,uBAAuB,KACjC,OAAO,CAAC,IAAI,CAyId,CAAC"}
@@ -230,7 +230,8 @@ const createAppHandler = async (name, options) => {
230
230
  const entityLabel = isChartType ? 'custom chart type' : 'data app';
231
231
  try {
232
232
  const slug = (0, exports.resolveLocalAppSlug)(name, options.slug);
233
- const appDir = path.join((0, contentAsCodePaths_1.getDownloadFolder)(options.path), 'apps', slug);
233
+ const contentRoot = (0, contentAsCodePaths_1.getDownloadFolder)(options.path);
234
+ const appDir = path.join(contentRoot, isChartType ? 'chart-types' : 'apps', slug);
234
235
  await assertAppDirectoryAvailable(appDir);
235
236
  await assertNpmAvailable();
236
237
  // Validate auth, project, and slug availability before asking the
@@ -305,8 +306,8 @@ const createAppHandler = async (name, options) => {
305
306
  }
306
307
  globalState_1.default.log(styles.success(`Created ${entityLabel} "${name}" at ${appDir}`));
307
308
  globalState_1.default.log(isChartType
308
- ? `\nNext:\n cd ${JSON.stringify(appDir)}\n lightdash apps validate --build\n lightdash upload --chart-types ${slug}\n\nThen open any explore in Lightdash and pick "${name}" in the chart type picker.`
309
- : `\nNext:\n cd ${JSON.stringify(appDir)}\n npm run build\n lightdash upload --apps ${slug}`);
309
+ ? `\nNext:\n cd ${JSON.stringify(appDir)}\n lightdash apps validate --build\n lightdash upload --chart-types ${slug} --path ${JSON.stringify(contentRoot)}\n\nThen open any explore in Lightdash and pick "${name}" in the chart type picker.`
310
+ : `\nNext:\n cd ${JSON.stringify(appDir)}\n npm run build\n lightdash upload --apps ${slug} --path ${JSON.stringify(contentRoot)}`);
310
311
  success = true;
311
312
  }
312
313
  finally {
@@ -195,15 +195,19 @@ describe('createAppHandler', () => {
195
195
  input: '\u001B[B\n',
196
196
  }));
197
197
  });
198
- it('creates a custom chart type scaffold with the viz starter and no shadcn', async () => {
198
+ it.each([false, true])('creates an uploadable chart type scaffold (custom path: %s)', async (customPath) => {
199
199
  const root = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-create-app-'));
200
+ vi.spyOn(process, 'cwd').mockReturnValue(root);
201
+ const contentRoot = customPath
202
+ ? root
203
+ : path.join(root, 'lightdash');
200
204
  await (0, createApp_1.createAppHandler)('Radial Gauge', {
201
205
  description: 'A gauge with a needle',
202
- path: root,
206
+ path: customPath ? root : undefined,
203
207
  chartType: true,
204
208
  verbose: false,
205
209
  });
206
- const appDir = path.join(root, 'apps', 'radial-gauge');
210
+ const appDir = path.join(contentRoot, 'chart-types', 'radial-gauge');
207
211
  const bundle = await (0, appCodeFiles_1.readBundleFromDir)(appDir);
208
212
  expect(bundle.manifest.template).toBe('data_app_viz');
209
213
  expect(bundle.manifest.vizSchema).toEqual(createApp_1.CHART_TYPE_STARTER_VIZ_SCHEMA);
@@ -219,7 +223,15 @@ describe('createAppHandler', () => {
219
223
  await expect(fs_1.promises.access(path.join(appDir, '.claude/skills/developing-data-apps-locally/SKILL.md'))).rejects.toThrow();
220
224
  expect(await fs_1.promises.readFile(path.join(appDir, 'AGENTS.md'), 'utf8')).toContain('custom chart type');
221
225
  expect(await fs_1.promises.readFile(path.join(appDir, 'README.md'), 'utf8')).toContain('Radial Gauge');
222
- expect(globalState_1.default.log).toHaveBeenCalledWith(expect.stringContaining('upload --chart-types radial-gauge'));
226
+ const authoringDocs = await Promise.all([
227
+ 'README.md',
228
+ 'AGENTS.md',
229
+ '.claude/skills/developing-chart-types-locally/SKILL.md',
230
+ ].map((file) => fs_1.promises.readFile(path.join(appDir, file), 'utf8')));
231
+ for (const doc of authoringDocs) {
232
+ expect(doc).toContain('upload --chart-types <slug> --path ../..');
233
+ }
234
+ expect(globalState_1.default.log).toHaveBeenCalledWith(expect.stringContaining(`upload --chart-types radial-gauge --path ${JSON.stringify(contentRoot)}`));
223
235
  expect(analytics_1.LightdashAnalytics.track).toHaveBeenCalledWith({
224
236
  event: 'command.executed',
225
237
  properties: expect.objectContaining({
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const fs_1 = require("fs");
4
4
  const os_1 = require("os");
5
+ const yaml_1 = require("yaml");
5
6
  const scaffolding_1 = require("./scaffolding");
6
7
  describe('firstExistingDir', () => {
7
8
  it('returns the first path that exists when a later candidate exists', () => {
@@ -79,6 +80,13 @@ describe('buildStaticAuthoringFiles', () => {
79
80
  expect(text('.npmrc')).toContain('ignore-scripts=true');
80
81
  expect(text('.npmrc')).not.toContain('shamefully-hoist');
81
82
  });
83
+ it('ships a release-age policy for pnpm with the SDK exemption', () => {
84
+ expect((0, yaml_1.parse)(text('pnpm-workspace.yaml'))).toMatchObject({
85
+ minimumReleaseAge: 4320,
86
+ minimumReleaseAgeExclude: ['@lightdash/query-sdk'],
87
+ ignoreScripts: true,
88
+ });
89
+ });
82
90
  it('documents Cloud-parity validation builds', () => {
83
91
  for (const path of [
84
92
  'README.md',
package/dist/index.js CHANGED
@@ -451,7 +451,7 @@ appsProgram
451
451
  .option('--project <project uuid or slug>', 'Specify the project the app will use', parseProjectArgument, undefined)
452
452
  .option('-y, --assume-yes', 'approve npm package installation', false)
453
453
  .option('--verbose', undefined, false)
454
- .addHelpText('after', `\n${styles.bold('Examples:')}\n ${styles.title('⚡')}️lightdash ${styles.bold('apps create "Revenue explorer"')} ${styles.secondary('-- creates ./lightdash/apps/revenue-explorer')}\n ${styles.title('⚡')}️lightdash ${styles.bold('apps create "Radial gauge" --chart-type')} ${styles.secondary('-- creates a custom chart type at ./lightdash/apps/radial-gauge')}\n`)
454
+ .addHelpText('after', `\n${styles.bold('Examples:')}\n ${styles.title('⚡')}️lightdash ${styles.bold('apps create "Revenue explorer"')} ${styles.secondary('-- creates ./lightdash/apps/revenue-explorer')}\n ${styles.title('⚡')}️lightdash ${styles.bold('apps create "Radial gauge" --chart-type')} ${styles.secondary('-- creates a custom chart type at ./lightdash/chart-types/radial-gauge')}\n`)
455
455
  .action(createApp_1.createAppHandler);
456
456
  appsProgram
457
457
  .command('preview [path]')
@@ -2,7 +2,9 @@
2
2
 
3
3
  Two skills in `.claude/skills/` describe how to edit this app:
4
4
  - `lightdash-data-app` — the Lightdash SDK surface (querying data, filters, downloads).
5
- - `developing-data-apps-locally` — the local workflow: edit `src/`, `lightdash apps validate --build`, `lightdash apps preview`, `lightdash upload --apps <slug>`; the SDK is the only data access; `.lightdash/context/` holds the project's semantic layer and theme.
5
+ - `developing-data-apps-locally` — the local workflow: edit `src/`, `lightdash apps validate --build`, `lightdash apps preview`, `lightdash upload --apps <slug> --path ../..`; the SDK is the only data access; `.lightdash/context/` holds the project's semantic layer and theme.
6
+
7
+ Run these commands from this folder under `apps/<slug>/`. The upload path `../..` selects the Lightdash content root.
6
8
 
7
9
  Edit only `src/`. Root config files are read-only reference — the server rebuilds against a trusted template.
8
10
 
@@ -3,10 +3,12 @@
3
3
  Created or downloaded with the Lightdash CLI.
4
4
 
5
5
  ## Edit → build → upload
6
+ Run these commands from this folder under `apps/<slug>/`. The upload path `../..` selects the Lightdash content root.
7
+
6
8
  1. Edit files under `src/`.
7
9
  2. Run `lightdash apps validate` to check the source, manifest, dependencies, external-connection aliases, and semantic references against the downloaded context. Use `lightdash apps validate --build` to add the Cloud-parity Vite production build; use `--live` for fresh project explores or `--format json` in CI. `lightdash apps create` installs the initial dependencies after asking permission; after `lightdash download`, run `npm install` first if `node_modules` is absent. Custom dependencies are installed from `pnpm-lock.yaml` with a frozen lockfile and lifecycle scripts disabled. A build failure is a validation error with the Vite output and a non-zero exit.
8
10
  3. Optionally, preview against real data: `lightdash apps preview` (needs a successful `npm install`).
9
- 4. `lightdash upload --apps <slug>` (the `slug` from `lightdash-app.yml`) — Lightdash rebuilds and serves the app.
11
+ 4. `lightdash upload --apps <slug> --path ../..` (the `slug` from `lightdash-app.yml`) — Lightdash rebuilds and serves the app.
10
12
 
11
13
  Local preview uses your existing CLI login through a project- and route-restricted loopback proxy; the credential is not written into this folder or exposed to browser code. It runs local tooling as your OS user (with access to that user's files, including the existing CLI config) and shows data under your own permissions, so preview only source/dependencies you trust. Host-mediated features such as external connections and data-app-viz context still need testing after upload.
12
14
 
@@ -12,9 +12,11 @@ Edit only `src/`. Root config files are read-only reference — the server rebui
12
12
 
13
13
  ## The loop
14
14
 
15
+ Run these commands from this folder under `chart-types/<slug>/`. The upload path `../..` selects the Lightdash content root.
16
+
15
17
  1. Edit `src/` (and `vizSchema` in `lightdash-app.yml` when the declaration changes).
16
18
  2. `lightdash apps validate --build` — Cloud-parity Vite build; a failure is a validation error with the Vite output.
17
- 3. `lightdash upload --chart-types <slug>` — the server rebuilds; the chart type then appears in the explorer's chart type picker for that project.
19
+ 3. `lightdash upload --chart-types <slug> --path ../..` — the server rebuilds; the chart type then appears in the explorer's chart type picker for that project.
18
20
  4. Verify in Lightdash: open any explore, run a query, pick this chart type, and map its fields.
19
21
 
20
22
  There is no local preview for a chart type: `useVizContext()` waits for the Lightdash host, so the component renders nothing standalone (`lightdash apps preview` and `npm run dev` show a blank page). Upload and verify in the explorer instead.
@@ -3,9 +3,11 @@
3
3
  Created or downloaded with the Lightdash CLI. This is a **custom chart type** (a reusable visualization): one chart component that Lightdash hands data and settings to. It runs no query of its own — the same component is reused across many different queries.
4
4
 
5
5
  ## Edit → validate → upload
6
+ Run these commands from this folder under `chart-types/<slug>/`. The upload path `../..` selects the Lightdash content root.
7
+
6
8
  1. Edit files under `src/`. The component's contract with Lightdash — the fields it maps and the config options viewers can change — is declared in `lightdash-app.yml` under `vizSchema` and must match what `src/App.jsx` reads (see `.claude/skills/reusable-visualization`).
7
9
  2. Run `lightdash apps validate` to check the source and manifest; `lightdash apps validate --build` adds the Cloud-parity Vite production build.
8
- 3. `lightdash upload --chart-types <slug>` (the `slug` from `lightdash-app.yml`) — Lightdash rebuilds and serves it.
10
+ 3. `lightdash upload --chart-types <slug> --path ../..` (the `slug` from `lightdash-app.yml`) — Lightdash rebuilds and serves it.
9
11
  4. Open any explore in Lightdash, run a query, and pick this chart type in the chart type picker to see it against real data.
10
12
 
11
13
  There is no standalone preview: the component waits for the Lightdash host's data, so `npm run dev` shows a blank page. Upload and verify in the explorer.
@@ -19,9 +19,11 @@ The correspondence must be exact in both directions: every key the component rea
19
19
 
20
20
  ## The edit → validate → upload → verify loop
21
21
 
22
+ Run these commands from this folder under `chart-types/<slug>/`. The upload path `../..` selects the Lightdash content root.
23
+
22
24
  1. Edit files under `src/` (and `vizSchema` when the declaration changes).
23
25
  2. `lightdash apps validate` checks source and manifest (including that `vizSchema` parses); `lightdash apps validate --build` adds the Cloud-parity Vite production build. A build failure is a validation error with the Vite output.
24
- 3. `lightdash upload --chart-types <slug>` (the `slug` from `lightdash-app.yml`) — the server rebuilds and serves it.
26
+ 3. `lightdash upload --chart-types <slug> --path ../..` (the `slug` from `lightdash-app.yml`) — the server rebuilds and serves it.
25
27
  4. Verify in Lightdash: open any explore, run a query with at least the required fields' shapes (e.g. a dimension and a metric), pick this chart type in the chart type picker, and map its fields. Check every config option you declared actually changes the chart.
26
28
 
27
29
  **There is no standalone preview.** `useVizContext()` waits for the Lightdash host to push context, so outside Lightdash the component renders nothing: `npm run dev` and `lightdash apps preview` show a blank page. Do not build a mock harness or feed the hook fake data to work around this — upload and verify in the explorer instead.
@@ -27,9 +27,11 @@ You are editing a Lightdash **data app** that was created or downloaded with the
27
27
 
28
28
  ## The edit → build → upload loop
29
29
 
30
+ Run these commands from this folder under `apps/<slug>/`. The upload path `../..` selects the Lightdash content root.
31
+
30
32
  1. Edit files under `src/` only.
31
33
  2. Run `lightdash apps validate` to check the source, manifest, dependencies, external-connection aliases, and semantic references against the downloaded context. Use `lightdash apps validate --build` to add the Cloud-parity Vite production build; use `--live` to check against fresh project explores or `--format json` in CI. A green run reports any call sites it could not fully analyze instead of silently claiming complete coverage.
32
- 3. `lightdash upload --apps <slug>` (the `slug` from this folder's `lightdash-app.yml`) — the **server** rebuilds and serves the app. The server rebuild remains the final result that ships.
34
+ 3. `lightdash upload --apps <slug> --path ../..` (the `slug` from this folder's `lightdash-app.yml`) — the **server** rebuilds and serves the app. The server rebuild remains the final result that ships.
33
35
 
34
36
  ## Cloud-parity local builds
35
37
 
@@ -2,6 +2,7 @@ packages: []
2
2
  # pnpm 11 reads settings from here; the .npmrc copies remain for pnpm <=10.
3
3
  shamefullyHoist: true
4
4
  ignoreWorkspaceRootCheck: true
5
+ minimumReleaseAge: 4320 # 3 days
5
6
  # The pinned SDK version is often <3 days old; exempt it from release-age policies
6
7
  minimumReleaseAgeExclude:
7
8
  - '@lightdash/query-sdk'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "2.163.1",
3
+ "version": "2.163.2",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -45,8 +45,8 @@
45
45
  "unique-names-generator": "4.7.1",
46
46
  "uuid": "11.1.1",
47
47
  "yaml": "2.8.3",
48
- "@lightdash/common": "2.163.1",
49
- "@lightdash/warehouses": "2.163.1"
48
+ "@lightdash/common": "2.163.2",
49
+ "@lightdash/warehouses": "2.163.2"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/inquirer": "8.2.4",