@lightdash/cli 1.76.1 → 1.78.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.
@@ -28,6 +28,7 @@ export declare const writeDependenciesToDir: (dir: string, deps: DataAppDependen
28
28
  export type LocalAppDependencies = {
29
29
  packageJson: string;
30
30
  lockfile: string | null;
31
+ hasNpmLockfile: boolean;
31
32
  };
32
33
  /**
33
34
  * Reads package.json (+ pnpm-lock.yaml when present) from the app folder
@@ -1 +1 @@
1
- {"version":3,"file":"appCodeFiles.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/appCodeFiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAChC,MAAM,mBAAmB,CAAC;AAO3B;;;;GAIG;AACH,eAAO,MAAM,aAAa,SAChB,MAAM,WACH,MAAM,gBACD,GAAG,CAAC,MAAM,CAAC,KAC1B,MAcF,CAAC;AAEF,eAAO,MAAM,eAAe,QACnB,MAAM,SACJ,eAAe,EAAE,KACzB,OAAO,CAAC,IAAI,CAsBd,CAAC;AAEF,eAAO,MAAM,iBAAiB,QACrB,MAAM,WACF,cAAc,KACxB,OAAO,CAAC,IAAI,CAiBd,CAAC;AAEF,eAAO,MAAM,gBAAgB,QACpB,MAAM,QACL,WAAW,KAClB,OAAO,CAAC,IAAI,CAWd,CAAC;AAmCF,eAAO,MAAM,eAAe,SAClB,WAAW,qBACE,MAAM,QACnB;IACF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,KACF,wBAqBF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACnB,eAAe,gBACX,GAAG,CAAC,MAAM,CAAC,KAC1B,MAgBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAC1B,MAAM,QACL,mBAAmB,KAC1B,OAAO,CAAC,IAAI,CAGd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAC;IAKpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAC3B,MAAM,KACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CA6BrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,eAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wBACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7C,MAAM,EAOH,CAAC;AAEP;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,yBACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,eAC/B,MAAM,KACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,SAC3B,WAAW,cACL,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAC5B,mBAAmB,KAC1B,WAC4E,CAAC;AAuBhF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,QAC1B,MAAM,YACD,eAAe,KAC1B,OAAO,CAAC,OAAO,CAqBjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,QACvB,MAAM,KACZ,OAAO,CAAC,eAAe,CAYzB,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAe,MAAM,KAAG,OAAO,CAAC,WAAW,CAYxE,CAAC"}
1
+ {"version":3,"file":"appCodeFiles.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/appCodeFiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAChC,MAAM,mBAAmB,CAAC;AAO3B;;;;GAIG;AACH,eAAO,MAAM,aAAa,SAChB,MAAM,WACH,MAAM,gBACD,GAAG,CAAC,MAAM,CAAC,KAC1B,MAcF,CAAC;AAEF,eAAO,MAAM,eAAe,QACnB,MAAM,SACJ,eAAe,EAAE,KACzB,OAAO,CAAC,IAAI,CAsBd,CAAC;AAEF,eAAO,MAAM,iBAAiB,QACrB,MAAM,WACF,cAAc,KACxB,OAAO,CAAC,IAAI,CAiBd,CAAC;AAEF,eAAO,MAAM,gBAAgB,QACpB,MAAM,QACL,WAAW,KAClB,OAAO,CAAC,IAAI,CAWd,CAAC;AAmCF,eAAO,MAAM,eAAe,SAClB,WAAW,qBACE,MAAM,QACnB;IACF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,KACF,wBAqBF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACnB,eAAe,gBACX,GAAG,CAAC,MAAM,CAAC,KAC1B,MAgBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAC1B,MAAM,QACL,mBAAmB,KAC1B,OAAO,CAAC,IAAI,CAGd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAC;IAKpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAIxB,cAAc,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAC3B,MAAM,KACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAmCrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,eAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wBACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7C,MAAM,EAOH,CAAC;AAEP;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,yBACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,eAC/B,MAAM,KACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,SAC3B,WAAW,cACL,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAC5B,mBAAmB,KAC1B,WAC4E,CAAC;AAuBhF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,QAC1B,MAAM,YACD,eAAe,KAC1B,OAAO,CAAC,OAAO,CAqBjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,QACvB,MAAM,KACZ,OAAO,CAAC,eAAe,CAYzB,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAe,MAAM,KAAG,OAAO,CAAC,WAAW,CAYxE,CAAC"}
@@ -154,7 +154,8 @@ exports.writeDependenciesToDir = writeDependenciesToDir;
154
154
  const readDependenciesFromDir = async (dir) => {
155
155
  const pkgJsonPath = path.join(dir, 'package.json');
156
156
  const lockfilePath = path.join(dir, 'pnpm-lock.yaml');
157
- const [pkgJsonExists, lockfileExists] = await Promise.all([
157
+ const npmLockfilePath = path.join(dir, 'package-lock.json');
158
+ const [pkgJsonExists, lockfileExists, npmLockfileExists] = await Promise.all([
158
159
  fs_1.promises
159
160
  .stat(pkgJsonPath)
160
161
  .then(() => true)
@@ -163,6 +164,10 @@ const readDependenciesFromDir = async (dir) => {
163
164
  .stat(lockfilePath)
164
165
  .then(() => true)
165
166
  .catch(() => false),
167
+ fs_1.promises
168
+ .stat(npmLockfilePath)
169
+ .then(() => true)
170
+ .catch(() => false),
166
171
  ]);
167
172
  if (!pkgJsonExists && !lockfileExists)
168
173
  return null;
@@ -173,7 +178,7 @@ const readDependenciesFromDir = async (dir) => {
173
178
  fs_1.promises.readFile(pkgJsonPath, 'utf-8'),
174
179
  lockfileExists ? fs_1.promises.readFile(lockfilePath, 'utf-8') : null,
175
180
  ]);
176
- return { packageJson, lockfile };
181
+ return { packageJson, lockfile, hasNpmLockfile: npmLockfileExists };
177
182
  };
178
183
  exports.readDependenciesFromDir = readDependenciesFromDir;
179
184
  /**
@@ -295,6 +295,7 @@ describe('readDependenciesFromDir', () => {
295
295
  expect(result).not.toBeNull();
296
296
  expect(result?.packageJson).toBe(makePackageJson());
297
297
  expect(result?.lockfile).toBe(LOCKFILE_CONTENT);
298
+ expect(result?.hasNpmLockfile).toBe(false);
298
299
  });
299
300
  // The download scaffold always writes package.json but never a lockfile,
300
301
  // so this state is every freshly downloaded template-only app — it must
@@ -310,6 +311,13 @@ describe('readDependenciesFromDir', () => {
310
311
  await fs_1.promises.writeFile(path.join(dir, 'pnpm-lock.yaml'), LOCKFILE_CONTENT);
311
312
  await expect((0, appCodeFiles_1.readDependenciesFromDir)(dir)).rejects.toThrow(/package\.json/);
312
313
  });
314
+ it('flags a stray package-lock.json when the pnpm lockfile is absent', async () => {
315
+ await fs_1.promises.writeFile(path.join(dir, 'package.json'), makePackageJson());
316
+ await fs_1.promises.writeFile(path.join(dir, 'package-lock.json'), '{}');
317
+ const result = await (0, appCodeFiles_1.readDependenciesFromDir)(dir);
318
+ expect(result?.lockfile).toBeNull();
319
+ expect(result?.hasNpmLockfile).toBe(true);
320
+ });
313
321
  });
314
322
  // ─── buildDepsWarningLines ────────────────────────────────────────────────────
315
323
  describe('buildDepsWarningLines', () => {
@@ -74,7 +74,7 @@ export declare const computeLinkedAppSlugs: (args: {
74
74
  /**
75
75
  * Pre-context servers return a download payload without `context`.
76
76
  */
77
- export declare const ensureDownloadedAppContext: (appUuid: string, code: DataAppCodeDownload) => DataAppCodeDownload;
77
+ export declare const ensureDownloadedAppContext: (appRef: string, code: DataAppCodeDownload) => DataAppCodeDownload;
78
78
  /**
79
79
  * Shown after uploading a bundle whose manifest predates slug identity —
80
80
  * uploads keep working via the uuid fallback, but the user should upgrade.
@@ -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":"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"}
@@ -125,9 +125,9 @@ exports.computeLinkedAppSlugs = computeLinkedAppSlugs;
125
125
  /**
126
126
  * Pre-context servers return a download payload without `context`.
127
127
  */
128
- const ensureDownloadedAppContext = (appUuid, code) => {
128
+ const ensureDownloadedAppContext = (appRef, code) => {
129
129
  if (code.context === undefined) {
130
- throw new Error(`This Lightdash server does not support app context downloads (app ${appUuid}). Upgrade the server, or use a CLI version matching your server.`);
130
+ throw new Error(`This Lightdash server does not support app context downloads (app ${code.manifest.slug ?? appRef}). Upgrade the server, or use a CLI version matching your server.`);
131
131
  }
132
132
  return code;
133
133
  };
@@ -1 +1 @@
1
- {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAOH,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAuB3B,MAAM,MAAM,uBAAuB,GAAG;IAClC,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;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;CACb,KAAG,eAUF,CAAC;AAiKH,eAAO,MAAM,gBAAgB,SACnB,MAAM,WACH,uBAAuB,KACjC,OAAO,CAAC,IAAI,CAwGd,CAAC"}
1
+ {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAOH,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAuB3B,MAAM,MAAM,uBAAuB,GAAG;IAClC,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;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;CACb,KAAG,eAUF,CAAC;AAiKH,eAAO,MAAM,gBAAgB,SACnB,MAAM,WACH,uBAAuB,KACjC,OAAO,CAAC,IAAI,CA2Gd,CAAC"}
@@ -186,12 +186,8 @@ const createAppHandler = async (name, options) => {
186
186
  const appDir = path.join((0, contentAsCodePaths_1.getDownloadFolder)(options.path), 'apps', slug);
187
187
  await assertAppDirectoryAvailable(appDir);
188
188
  await assertNpmAvailable();
189
- await confirmLocalPackageTooling(options.assumeYes ?? false);
190
- const staticFiles = (0, scaffolding_1.buildStaticAuthoringFiles)({
191
- appName: name,
192
- sdkVersion: env_1.CLI_VERSION,
193
- });
194
- await confirmDependencyInstall(parseDirectPackages(staticFiles), options.assumeYes ?? false);
189
+ // Validate auth, project, and slug availability before asking the
190
+ // user to approve any local package installation.
195
191
  await (0, apiClient_1.checkLightdashVersion)();
196
192
  const config = await (0, config_1.getConfig)();
197
193
  if (!config.context?.apiKey || !config.context.serverUrl) {
@@ -213,6 +209,12 @@ const createAppHandler = async (name, options) => {
213
209
  url: `/api/v1/ee/projects/${projectUuid}/apps/authoring-context?slug=${encodeURIComponent(slug)}`,
214
210
  body: undefined,
215
211
  });
212
+ await confirmLocalPackageTooling(options.assumeYes ?? false);
213
+ const staticFiles = (0, scaffolding_1.buildStaticAuthoringFiles)({
214
+ appName: name,
215
+ sdkVersion: env_1.CLI_VERSION,
216
+ });
217
+ await confirmDependencyInstall(parseDirectPackages(staticFiles), options.assumeYes ?? false);
216
218
  const manifest = (0, exports.buildLocalAppManifest)({
217
219
  name,
218
220
  description: options.description ?? '',
@@ -202,7 +202,9 @@ describe('createAppHandler', () => {
202
202
  path: root,
203
203
  verbose: false,
204
204
  })).rejects.toThrow('Data app creation cancelled');
205
- expect(apiClient_1.lightdashApi).not.toHaveBeenCalled();
205
+ // Preflight (auth, project, slug availability) runs before the
206
+ // prompts, so the context call has already happened by then.
207
+ expect(apiClient_1.lightdashApi).toHaveBeenCalledTimes(1);
206
208
  await expect(fs_1.promises.access(path.join(root, 'apps', 'revenue-explorer'))).rejects.toThrow();
207
209
  });
208
210
  it('does not list packages when local tooling approval is declined', async () => {
@@ -214,7 +216,24 @@ describe('createAppHandler', () => {
214
216
  })).rejects.toThrow('Data app creation cancelled');
215
217
  expect(promptMock).toHaveBeenCalledTimes(1);
216
218
  expect(globalState_1.default.log).not.toHaveBeenCalledWith(expect.stringContaining('react@19.2.5'));
217
- expect(apiClient_1.lightdashApi).not.toHaveBeenCalled();
219
+ });
220
+ it('asks for no approvals when the server rejects the slug', async () => {
221
+ const root = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-create-app-'));
222
+ vi.mocked(apiClient_1.lightdashApi).mockRejectedValueOnce(new Error('Slug already in use'));
223
+ await expect((0, createApp_1.createAppHandler)('Revenue Explorer', {
224
+ path: root,
225
+ verbose: false,
226
+ })).rejects.toThrow('Slug already in use');
227
+ expect(promptMock).not.toHaveBeenCalled();
228
+ });
229
+ it('asks for no approvals when not logged in', async () => {
230
+ const root = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-create-app-'));
231
+ vi.mocked(config_1.getConfig).mockResolvedValueOnce({});
232
+ await expect((0, createApp_1.createAppHandler)('Revenue Explorer', {
233
+ path: root,
234
+ verbose: false,
235
+ })).rejects.toThrow('Not logged in');
236
+ expect(promptMock).not.toHaveBeenCalled();
218
237
  });
219
238
  it('requires explicit approval in non-interactive mode', async () => {
220
239
  const root = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-create-app-'));
@@ -27,6 +27,15 @@ export declare const resolvePreviewTarget: (args: {
27
27
  projectUuid: string;
28
28
  }>;
29
29
  export declare const assertNodeModulesPresent: (appDir: string) => Promise<void>;
30
+ /**
31
+ * Preview needs the app's packages on disk. Mirrors the `apps create`
32
+ * approval posture: a strong warning plus a two-step confirm (both
33
+ * defaulting to No) before anything is downloaded to this machine.
34
+ */
35
+ export declare const ensureNodeModules: (args: {
36
+ appDir: string;
37
+ assumeYes: boolean;
38
+ }) => Promise<void>;
30
39
  /**
31
40
  * The login context can point at a different instance than the one the app
32
41
  * was downloaded from — the credential pre-flight passes there, but the
@@ -49,8 +58,11 @@ type AppsPreviewOptions = {
49
58
  project?: string;
50
59
  url?: string;
51
60
  token?: string;
61
+ port?: string;
62
+ assumeYes: boolean;
52
63
  verbose: boolean;
53
64
  };
65
+ export declare const resolvePreviewPort: (raw: string | undefined) => number | undefined;
54
66
  export declare const appsPreviewHandler: (pathArg: string | undefined, options: AppsPreviewOptions) => Promise<void>;
55
67
  export {};
56
68
  //# sourceMappingURL=preview.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/preview.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,SAAU;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CA2CxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,WACtC,MAAM,KACf,OAAO,CAAC,IAAI,CASd,CAAC;AAEF,eAAO,MAAM,oBAAoB,SAAgB;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAqBlD,CAAC;AAEF,eAAO,MAAM,wBAAwB,WACzB,MAAM,KACf,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAU;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB,KAAG,MACgT,CAAC;AAErT,eAAO,MAAM,uBAAuB,SAAgB;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,KAAG,OAAO,CAAC,OAAO,CAmBlB,CAAC;AAKF,eAAO,MAAM,6BAA6B,WAC9B,MAAM,KACf,OAAO,CAAC,OAAO,CAmBjB,CAAC;AAkBF,KAAK,kBAAkB,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAClB,MAAM,GAAG,SAAS,WAClB,kBAAkB,KAC5B,OAAO,CAAC,IAAI,CA+Gd,CAAC"}
1
+ {"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/handlers/apps/preview.ts"],"names":[],"mappings":"AAkBA;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,SAAU;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CA2CxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,WACtC,MAAM,KACf,OAAO,CAAC,IAAI,CAWd,CAAC;AAEF,eAAO,MAAM,oBAAoB,SAAgB;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAqBlD,CAAC;AAQF,eAAO,MAAM,wBAAwB,WACzB,MAAM,KACf,OAAO,CAAC,IAAI,CAMd,CAAC;AAyBF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SAAgB;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACtB,KAAG,OAAO,CAAC,IAAI,CAuEf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAU;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB,KAAG,MACgT,CAAC;AAErT,eAAO,MAAM,uBAAuB,SAAgB;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,KAAG,OAAO,CAAC,OAAO,CAmBlB,CAAC;AAKF,eAAO,MAAM,6BAA6B,WAC9B,MAAM,KACf,OAAO,CAAC,OAAO,CAmBjB,CAAC;AAkBF,KAAK,kBAAkB,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,QACtB,MAAM,GAAG,SAAS,KACxB,MAAM,GAAG,SASX,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAClB,MAAM,GAAG,SAAS,WAClB,kBAAkB,KAC5B,OAAO,CAAC,IAAI,CAiId,CAAC"}
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.appsPreviewHandler = exports.removeLegacyPreviewCredential = exports.preflightPreviewRequest = exports.projectNotFoundMessage = exports.assertNodeModulesPresent = exports.resolvePreviewTarget = exports.assertScaffoldingSupportsPreviewProxy = exports.buildPreviewChildEnv = void 0;
3
+ exports.appsPreviewHandler = exports.resolvePreviewPort = exports.removeLegacyPreviewCredential = exports.preflightPreviewRequest = exports.projectNotFoundMessage = exports.ensureNodeModules = exports.assertNodeModulesPresent = exports.resolvePreviewTarget = exports.assertScaffoldingSupportsPreviewProxy = exports.buildPreviewChildEnv = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const common_1 = require("@lightdash/common");
6
6
  const crypto_1 = require("crypto");
7
7
  const execa_1 = tslib_1.__importDefault(require("execa"));
8
8
  const fs_1 = require("fs");
9
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
9
10
  const path = tslib_1.__importStar(require("path"));
10
11
  const config_1 = require("../../config");
11
12
  const globalState_1 = tslib_1.__importDefault(require("../../globalState"));
@@ -76,7 +77,7 @@ const assertScaffoldingSupportsPreviewProxy = async (appDir) => {
76
77
  .readFile(path.join(appDir, 'vite.config.js'), 'utf-8')
77
78
  .catch(() => '');
78
79
  if (!viteConfig.includes('LIGHTDASH_PREVIEW_PROXY_TARGET')) {
79
- throw new Error(`This app's scaffolding predates the secure preview proxy. Re-download the app ('lightdash download --apps <appUuid>') to refresh vite.config.js, then run preview again.`);
80
+ throw new Error(`This app's scaffolding predates the secure preview proxy. Re-download the app ('lightdash download --apps ${path.basename(appDir)}') to refresh vite.config.js, then run preview again.`);
80
81
  }
81
82
  };
82
83
  exports.assertScaffoldingSupportsPreviewProxy = assertScaffoldingSupportsPreviewProxy;
@@ -100,16 +101,101 @@ const resolvePreviewTarget = async (args) => {
100
101
  };
101
102
  };
102
103
  exports.resolvePreviewTarget = resolvePreviewTarget;
104
+ const hasNodeModules = async (appDir) => fs_1.promises
105
+ .stat(path.join(appDir, 'node_modules'))
106
+ .then((s) => s.isDirectory())
107
+ .catch(() => false);
103
108
  const assertNodeModulesPresent = async (appDir) => {
104
- const isDir = await fs_1.promises
105
- .stat(path.join(appDir, 'node_modules'))
106
- .then((s) => s.isDirectory())
107
- .catch(() => false);
108
- if (!isDir) {
109
- throw new Error(`Dependencies are not installed. Run 'npm install' in ${appDir} first (preview does not auto-install).`);
109
+ if (!(await hasNodeModules(appDir))) {
110
+ throw new Error(`Dependencies are not installed. Run 'npm install' in ${appDir} first, or rerun with --assume-yes to approve the install.`);
110
111
  }
111
112
  };
112
113
  exports.assertNodeModulesPresent = assertNodeModulesPresent;
114
+ const readDirectPackages = async (appDir) => {
115
+ let raw;
116
+ try {
117
+ raw = await fs_1.promises.readFile(path.join(appDir, 'package.json'), 'utf-8');
118
+ }
119
+ catch {
120
+ return [];
121
+ }
122
+ try {
123
+ const parsed = JSON.parse(raw);
124
+ return Object.entries({
125
+ ...parsed.dependencies,
126
+ ...parsed.devDependencies,
127
+ })
128
+ .map(([packageName, version]) => `${packageName}@${version}`)
129
+ .sort();
130
+ }
131
+ catch {
132
+ return [];
133
+ }
134
+ };
135
+ /**
136
+ * Preview needs the app's packages on disk. Mirrors the `apps create`
137
+ * approval posture: a strong warning plus a two-step confirm (both
138
+ * defaulting to No) before anything is downloaded to this machine.
139
+ */
140
+ const ensureNodeModules = async (args) => {
141
+ if (await hasNodeModules(args.appDir))
142
+ return;
143
+ const interactive = !globalState_1.default.isNonInteractive() &&
144
+ process.stdin.isTTY === true &&
145
+ process.stdout.isTTY === true;
146
+ if (!args.assumeYes && !interactive) {
147
+ await (0, exports.assertNodeModulesPresent)(args.appDir);
148
+ return;
149
+ }
150
+ globalState_1.default.log(styles.warning([
151
+ '⚠ Local package installation',
152
+ 'Previewing this app requires its npm packages, which are not installed yet. Continuing downloads third-party packages through npm into the app folder.',
153
+ 'Dependency lifecycle scripts are disabled, but npm will access the network and write files on this machine.',
154
+ 'Only continue if you trust the packages this app declares.',
155
+ ].join('\n')));
156
+ if (!args.assumeYes) {
157
+ const { confirmed } = await inquirer_1.default.prompt([
158
+ {
159
+ type: 'confirm',
160
+ name: 'confirmed',
161
+ message: 'Continue and review the packages to be installed?',
162
+ default: false,
163
+ },
164
+ ]);
165
+ if (!confirmed) {
166
+ throw new Error('Preview cancelled.');
167
+ }
168
+ }
169
+ const directPackages = await readDirectPackages(args.appDir);
170
+ globalState_1.default.log([
171
+ 'Previewing this data app will install these direct npm packages:',
172
+ ...directPackages.map((packageSpec) => ` - ${packageSpec}`),
173
+ '\nDependency lifecycle scripts will be disabled.',
174
+ ].join('\n'));
175
+ if (!args.assumeYes) {
176
+ const { confirmed } = await inquirer_1.default.prompt([
177
+ {
178
+ type: 'confirm',
179
+ name: 'confirmed',
180
+ message: 'Install these packages and start the preview?',
181
+ default: false,
182
+ },
183
+ ]);
184
+ if (!confirmed) {
185
+ throw new Error('Preview cancelled.');
186
+ }
187
+ }
188
+ await (0, execa_1.default)('npm', ['install', '--include=dev', '--ignore-scripts', '--no-package-lock'], {
189
+ cwd: args.appDir,
190
+ env: {
191
+ ...process.env,
192
+ npm_config_ignore_scripts: 'true',
193
+ npm_config_package_lock: 'false',
194
+ },
195
+ stdio: 'inherit',
196
+ });
197
+ };
198
+ exports.ensureNodeModules = ensureNodeModules;
113
199
  /**
114
200
  * The login context can point at a different instance than the one the app
115
201
  * was downloaded from — the credential pre-flight passes there, but the
@@ -174,8 +260,19 @@ const isUserStoppedDevServer = (error) => {
174
260
  exitCode === 130 ||
175
261
  exitCode === 143);
176
262
  };
263
+ const resolvePreviewPort = (raw) => {
264
+ if (raw === undefined)
265
+ return undefined;
266
+ const port = Number(raw);
267
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
268
+ throw new common_1.ParameterError(`--port must be an integer between 1 and 65535, got "${raw}".`);
269
+ }
270
+ return port;
271
+ };
272
+ exports.resolvePreviewPort = resolvePreviewPort;
177
273
  const appsPreviewHandler = async (pathArg, options) => {
178
274
  globalState_1.default.setVerbose(options.verbose);
275
+ const devServerPort = (0, exports.resolvePreviewPort)(options.port);
179
276
  const config = await (0, config_1.getConfig)();
180
277
  const serverUrl = options.url ?? config.context?.serverUrl;
181
278
  // getConfig() already folds LIGHTDASH_API_KEY into context.apiKey, so the
@@ -196,7 +293,10 @@ const appsPreviewHandler = async (pathArg, options) => {
196
293
  projectFlag: options.project,
197
294
  cwd: process.cwd(),
198
295
  });
199
- await (0, exports.assertNodeModulesPresent)(target.appDir);
296
+ await (0, exports.ensureNodeModules)({
297
+ appDir: target.appDir,
298
+ assumeYes: options.assumeYes,
299
+ });
200
300
  await (0, exports.assertScaffoldingSupportsPreviewProxy)(target.appDir);
201
301
  // Pre-flight the credential before starting vite: an expired/revoked
202
302
  // token would otherwise surface as opaque query failures inside the app.
@@ -233,11 +333,19 @@ const appsPreviewHandler = async (pathArg, options) => {
233
333
  projectUuid: target.projectUuid,
234
334
  nonce: proxyNonce,
235
335
  });
236
- globalState_1.default.log(`Preview proxy on 127.0.0.1:${proxy.port} — your credential is not passed to the app; SDK traffic is restricted to project ${target.projectUuid}.`);
336
+ globalState_1.default.log(`Auth proxy on 127.0.0.1:${proxy.port} (not the app URL) — your credential is not passed to the app; SDK traffic is restricted to project ${target.projectUuid}.`);
237
337
  globalState_1.default.log(styles.warning(`Preview renders YOUR data with YOUR permissions and user attributes — viewers of the deployed app may see different data.`));
238
- globalState_1.default.log(`Starting dev server (Ctrl-C to stop)…`);
338
+ globalState_1.default.log(devServerPort !== undefined
339
+ ? `Starting dev server — open http://localhost:${devServerPort} when it's ready (Ctrl-C to stop)…`
340
+ : `Starting dev server — open the "Local" URL it prints below (Ctrl-C to stop)…`);
239
341
  try {
240
- await (0, execa_1.default)('npm', ['run', 'dev'], {
342
+ await (0, execa_1.default)('npm', [
343
+ 'run',
344
+ 'dev',
345
+ ...(devServerPort !== undefined
346
+ ? ['--', '--port', String(devServerPort), '--strictPort']
347
+ : []),
348
+ ], {
241
349
  cwd: target.appDir,
242
350
  stdio: 'inherit',
243
351
  extendEnv: false,
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const execa_1 = tslib_1.__importDefault(require("execa"));
4
5
  const fs_1 = require("fs");
6
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
5
7
  const os = tslib_1.__importStar(require("os"));
6
8
  const path = tslib_1.__importStar(require("path"));
9
+ const globalState_1 = tslib_1.__importDefault(require("../../globalState"));
7
10
  const utils_1 = require("../utils");
8
11
  const appCodeFiles_1 = require("./appCodeFiles");
9
12
  const preview_1 = require("./preview");
13
+ vi.mock('execa');
14
+ vi.mock('inquirer', () => ({ default: { prompt: vi.fn() } }));
10
15
  const previewBundle = {
11
16
  manifest: {
12
17
  codeVersion: 1,
@@ -115,7 +120,71 @@ describe('assertNodeModulesPresent', () => {
115
120
  });
116
121
  it('errors telling the user to npm install, without installing', async () => {
117
122
  const dir = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-prev-'));
118
- await expect((0, preview_1.assertNodeModulesPresent)(dir)).rejects.toThrow(/Run 'npm install' in .* \(preview does not auto-install\)/);
123
+ await expect((0, preview_1.assertNodeModulesPresent)(dir)).rejects.toThrow(/Run 'npm install' in .*, or rerun with --assume-yes/);
124
+ });
125
+ });
126
+ describe('resolvePreviewPort', () => {
127
+ it('returns undefined when no port is given', () => {
128
+ expect((0, preview_1.resolvePreviewPort)(undefined)).toBeUndefined();
129
+ });
130
+ it('parses a valid port', () => {
131
+ expect((0, preview_1.resolvePreviewPort)('4000')).toBe(4000);
132
+ });
133
+ it.each(['0', '-1', '65536', 'abc', '1.5'])('rejects invalid port %s', (raw) => {
134
+ expect(() => (0, preview_1.resolvePreviewPort)(raw)).toThrow(/--port must be an integer/);
135
+ });
136
+ });
137
+ describe('ensureNodeModules', () => {
138
+ const promptMock = inquirer_1.default.prompt;
139
+ let dir;
140
+ beforeEach(async () => {
141
+ dir = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-prev-'));
142
+ vi.mocked(execa_1.default).mockReset();
143
+ promptMock.mockReset();
144
+ vi.spyOn(globalState_1.default, 'log').mockImplementation(() => { });
145
+ vi.spyOn(globalState_1.default, 'isNonInteractive').mockReturnValue(false);
146
+ });
147
+ afterEach(async () => {
148
+ vi.restoreAllMocks();
149
+ await fs_1.promises.rm(dir, { recursive: true, force: true });
150
+ });
151
+ it('does nothing when node_modules exists', async () => {
152
+ await fs_1.promises.mkdir(path.join(dir, 'node_modules'));
153
+ await (0, preview_1.ensureNodeModules)({ appDir: dir, assumeYes: false });
154
+ expect(execa_1.default).not.toHaveBeenCalled();
155
+ expect(promptMock).not.toHaveBeenCalled();
156
+ });
157
+ it('fails fast without installing when not interactive', async () => {
158
+ vi.spyOn(globalState_1.default, 'isNonInteractive').mockReturnValue(true);
159
+ await expect((0, preview_1.ensureNodeModules)({ appDir: dir, assumeYes: false })).rejects.toThrow(/Run 'npm install'/);
160
+ expect(execa_1.default).not.toHaveBeenCalled();
161
+ expect(promptMock).not.toHaveBeenCalled();
162
+ });
163
+ it('installs without prompting with --assume-yes', async () => {
164
+ await (0, preview_1.ensureNodeModules)({ appDir: dir, assumeYes: true });
165
+ expect(promptMock).not.toHaveBeenCalled();
166
+ expect(execa_1.default).toHaveBeenCalledWith('npm', [
167
+ 'install',
168
+ '--include=dev',
169
+ '--ignore-scripts',
170
+ '--no-package-lock',
171
+ ], expect.objectContaining({ cwd: dir }));
172
+ });
173
+ it('cancels without installing when the warning prompt is declined', async () => {
174
+ const stdinTty = process.stdin.isTTY;
175
+ const stdoutTty = process.stdout.isTTY;
176
+ process.stdin.isTTY = true;
177
+ process.stdout.isTTY = true;
178
+ promptMock.mockResolvedValueOnce({ confirmed: false });
179
+ try {
180
+ await expect((0, preview_1.ensureNodeModules)({ appDir: dir, assumeYes: false })).rejects.toThrow('Preview cancelled.');
181
+ }
182
+ finally {
183
+ process.stdin.isTTY = stdinTty;
184
+ process.stdout.isTTY = stdoutTty;
185
+ }
186
+ expect(promptMock).toHaveBeenCalledTimes(1);
187
+ expect(execa_1.default).not.toHaveBeenCalled();
119
188
  });
120
189
  });
121
190
  describe('projectNotFoundMessage', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/handlers/download.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,WAAW,EAyBX,WAAW,EAGX,eAAe,EAEf,wBAAwB,EAgBxB,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAIH,KAAK,0BAA0B,EAClC,MAAM,iCAAiC,CAAC;AAiEzC,OAAO,EACH,sBAAsB,EAGtB,cAAc,EACd,qBAAqB,EAKrB,cAAc,EACd,cAAc,EACd,8BAA8B,EAC9B,yBAAyB,EACzB,YAAY,EACZ,qBAAqB,EACrB,eAAe,EAElB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,sBAAsB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,EAAE,OAAO,CAAC;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,EAAE,OAAO,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,0BAA0B,EAAE,OAAO,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,0BAA0B,EAAE,OAAO,CAAC;IACpC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAIF,QAAA,MAAM,sBAAsB,qDAKzB,IAAI,CACH,sBAAsB,EACtB,YAAY,GAAG,eAAe,GAAG,QAAQ,GAAG,UAAU,CACzD,KAAG,OAEoE,CAAC;AAEzE,QAAA,MAAM,iBAAiB,oIAWpB,IAAI,CACH,sBAAsB,EACpB,YAAY,GACZ,QAAQ,GACR,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,cAAc,GACd,qBAAqB,GACrB,cAAc,GACd,qBAAqB,GACrB,MAAM,CACX,KAAG,OAYuC,CAAC;AAgF5C,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,wBAAwB,UACnB,WAAW,oBACA,OAAO,KAC1B,WAQY,CAAC;AAgXhB,KAAK,mBAAmB,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAkDjE,QAAA,MAAM,6BAA6B,eACnB,eAAe,EAAE,KAC9B,MAAM,EAWR,CAAC;AAIF,QAAA,MAAM,sBAAsB,WAAY,WAAW,EAAE,KAAG,MAAM,EAM7D,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,MAAM,EAAE,WAAW,EAAE,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,eAAe,QACnB,MAAM,EAAE,QACP,mBAAmB,aACd,MAAM,eACJ,MAAM,eACN,MAAM,gBACN,OAAO,WACZ,OAAO,eACH,OAAO,qBACD,OAAO,eACb,OAAO,eACN,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KACtC,OAAO,CAAC,qBAAqB,CAuJ/B,CAAC;AAsDF,QAAA,MAAM,8BAA8B,UAAW,OAAO,KAAG,OACmB,CAAC;AAE7E;;;;;GAKG;AACH,QAAA,MAAM,0BAA0B,cACjB,MAAM,cACL,MAAM,EAAE,eACP,MAAM,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAoCvB,CAAC;AAaF,QAAA,MAAM,kBAAkB,cACT,MAAM,SACV,MAAM,EAAE,WACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SACxB,OAAO,aACH,OAAO,eACL,MAAM,mBACH,MAAM,EAAE,KACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmEhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,SAAU,MAAM,KAAG,MAGzC,CAAC;AAQzB;;;;;;GAMG;AACH,QAAA,MAAM,qCAAqC,UAAW,OAAO,KAAG,OAElB,CAAC;AAE/C,QAAA,MAAM,0BAA0B,UAAW,OAAO,KAAG,OAEP,CAAC;AA8E/C,QAAA,MAAM,2BAA2B,gBAChB,MAAM,KACpB,OAAO,CAAC,wBAAwB,EAAE,CAOpC,CAAC;AAEF,QAAA,MAAM,yBAAyB,cAChB,MAAM,SACV,MAAM,EAAE,WACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SACxB,OAAO,aACH,OAAO,eACL,MAAM,KACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA8EhC,CAAC;AAgDF,QAAA,MAAM,gBAAgB,cACP,MAAM,OACZ,MAAM,EAAE,YACH,OAAO,eACJ,MAAM,KACpB,OAAO,CAAC,MAAM,CAqDhB,CAAC;AAEF,QAAA,MAAM,gBAAgB,gBACL,MAAM,KACpB,OAAO,CAAC,WAAW,EAAE,CAOvB,CAAC;AAcF,QAAA,MAAM,cAAc,cACL,MAAM,SACV,MAAM,EAAE,WACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SACxB,OAAO,eACD,MAAM,aACT,OAAO,KAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgDhC,CAAC;AAgLF,eAAO,MAAM,eAAe,YACf,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAytBd,CAAC;AAiDF,QAAA,MAAM,sBAAsB,WAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SACvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,0BAA0B,CAAA;CAoBxD,CAAC;AA6aF,QAAA,MAAM,2BAA2B,gEAK9B;IACC,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,eAAe,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC5B,KAAG,MAAM,EAWT,CAAC;AAEF,QAAA,MAAM,sBAAsB,mBACR,MAAM,EAAE,eACX,MAAM,oBACF,CAAC,eAAe,GAAG;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,KAClE,OAAO,CAAC,MAAM,EAAE,CAId,CAAC;AAEN,QAAA,MAAM,oBAAoB,mBACN,MAAM,EAAE,eACX,MAAM,oBACF,CAAC,eAAe,GAAG;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,KAClE,OAAO,CAAC,MAAM,EAAE,CAId,CAAC;AAIN,QAAA,MAAM,0BAA0B,eAChB,OAAO,kBACH,MAAM,EAAE,KACzB,OAAoD,CAAC;AAExD,eAAO,MAAM,aAAa,YACb,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAs4Bd,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BvB,CAAC"}
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/handlers/download.ts"],"names":[],"mappings":"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"}
@@ -2001,7 +2001,9 @@ const uploadHandler = async (options) => {
2001
2001
  }
2002
2002
  if (Object.keys(customDeps).length > 0) {
2003
2003
  if (rawDeps.lockfile === null) {
2004
- globalState_1.default.log(styles.error(`Skipping "${subDir.name}": it declares custom dependencies but has no pnpm-lock.yaml. Run 'pnpm install' in the app folder to generate one, then upload again.`));
2004
+ globalState_1.default.log(styles.error(rawDeps.hasNpmLockfile
2005
+ ? `Skipping "${subDir.name}": custom dependencies require a pnpm lockfile — the server builds with pnpm, so package-lock.json is not used. Run 'pnpm install' in the app folder to generate pnpm-lock.yaml, then upload again.`
2006
+ : `Skipping "${subDir.name}": it declares custom dependencies but has no pnpm-lock.yaml (the server builds with pnpm). Run 'pnpm install' in the app folder to generate one, then upload again.`));
2005
2007
  appsFailed += 1;
2006
2008
  // eslint-disable-next-line no-continue
2007
2009
  continue;
package/dist/index.js CHANGED
@@ -376,7 +376,7 @@ const downloadCommand = commander_1.program
376
376
  .option('--include-scheduled-deliveries', 'include all scheduled deliveries in the download', false)
377
377
  .option('--include-all', 'include all optional content in the download', false)
378
378
  .option('--strip-pivot-series', 'strip per-value pivot series config from chart YAML for portable downloads', false)
379
- .option('--apps <appReferences...>', 'Download only the specified data apps, by UUID, slug, or app URL (enterprise). Works for apps not added to a space.')
379
+ .option('--apps <appReferences...>', 'Download only the specified data apps, by slug, app URL, or UUID (enterprise). Works for apps not added to a space.')
380
380
  .option('--include-apps', "Include all of the project's data apps (enterprise), capped at --apps-limit (default: 50)", false)
381
381
  .option('--apps-limit <number>', 'Maximum number of data apps downloaded by --include-apps or --include-all (default: 50)', undefined)
382
382
  .option('--apps-only', 'Download only data apps (implies --skip-charts --skip-dashboards --skip-spaces). Requires --apps <appReferences...>, --include-apps, or --include-all.', false)
@@ -413,7 +413,7 @@ const uploadCommand = commander_1.program
413
413
  .option('--include-virtual-views', 'Include the virtual views used by the charts and dashboards being uploaded', false)
414
414
  .option('--validate', 'Validate charts and dashboards after upload', false)
415
415
  .option('--gzip', 'Enable gzip compression for request bodies', false)
416
- .option('--apps <appReferences...>', 'Upload only the specified data apps, by UUID, slug, or app URL (enterprise).')
416
+ .option('--apps <appReferences...>', 'Upload only the specified data apps, by slug — the app folder name (enterprise).')
417
417
  .option('--include-apps', 'Upload all app folders on disk (enterprise).', false)
418
418
  .option('--create-new', 'Always create a new app from the uploaded code instead of updating the app referenced by lightdash-app.yml. The new app gets a fresh slug.', false)
419
419
  .option('--organization', 'upload all organization-scoped resources without selecting a project', false)
@@ -439,6 +439,8 @@ appsProgram
439
439
  .option('--project <project uuid>', 'preview against a specific project (default: the projectUuid in lightdash-app.yml)')
440
440
  .option('--url <url>', 'Lightdash server URL (default: your login config)')
441
441
  .option('--token <token>', 'API key / personal access token (default: your login config)')
442
+ .option('-y, --assume-yes', 'assume yes to the dependency install prompts when node_modules is missing', false)
443
+ .option('--port <port>', 'port for the app dev server (default: Vite picks one, usually 5173)')
442
444
  .option('--verbose', undefined, false)
443
445
  .action(preview_1.appsPreviewHandler);
444
446
  commander_1.program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "1.76.1",
3
+ "version": "1.78.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  "unique-names-generator": "4.7.1",
42
42
  "uuid": "11.1.1",
43
43
  "yaml": "2.8.3",
44
- "@lightdash/warehouses": "1.76.1",
45
- "@lightdash/common": "1.76.1"
44
+ "@lightdash/common": "1.78.0",
45
+ "@lightdash/warehouses": "1.78.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/inquirer": "8.2.4",