@lightdash/cli 2.163.1 → 2.164.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/dist/.tsbuildinfo +1 -1
- package/dist/handlers/apps/appsDownload.d.ts +2 -5
- package/dist/handlers/apps/appsDownload.d.ts.map +1 -1
- package/dist/handlers/apps/appsDownload.js +8 -5
- package/dist/handlers/apps/appsDownload.test.js +4 -0
- package/dist/handlers/apps/createApp.d.ts.map +1 -1
- package/dist/handlers/apps/createApp.js +4 -3
- package/dist/handlers/apps/createApp.test.js +16 -4
- package/dist/handlers/apps/scaffolding.test.js +8 -0
- package/dist/index.js +1 -1
- package/dist/vendor/authoring/AGENTS.md.tmpl +3 -1
- package/dist/vendor/authoring/README.md.tmpl +3 -1
- package/dist/vendor/authoring/chart-type/AGENTS.md.tmpl +3 -1
- package/dist/vendor/authoring/chart-type/README.md.tmpl +3 -1
- package/dist/vendor/authoring/developing-chart-types-locally/SKILL.md +3 -1
- package/dist/vendor/authoring/developing-data-apps-locally/SKILL.md +3 -1
- package/dist/vendor/template/pnpm-workspace.yaml +1 -0
- package/package.json +3 -3
|
@@ -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
|
|
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
|
-
*
|
|
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":"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
|
|
1
|
+
{"version":3,"file":"appsDownload.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/appsDownload.ts"],"names":[],"mappings":"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"}
|
|
@@ -198,19 +198,22 @@ const classifyAppDownloadError = (err) => {
|
|
|
198
198
|
};
|
|
199
199
|
exports.classifyAppDownloadError = classifyAppDownloadError;
|
|
200
200
|
/**
|
|
201
|
-
* Sums changes entries that represent actual upserts
|
|
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
|
-
*
|
|
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,
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
3
|
+
"version": "2.164.0",
|
|
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.
|
|
49
|
-
"@lightdash/warehouses": "2.
|
|
48
|
+
"@lightdash/common": "2.164.0",
|
|
49
|
+
"@lightdash/warehouses": "2.164.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/inquirer": "8.2.4",
|