@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/handlers/apps/appCodeFiles.d.ts +1 -0
- package/dist/handlers/apps/appCodeFiles.d.ts.map +1 -1
- package/dist/handlers/apps/appCodeFiles.js +7 -2
- package/dist/handlers/apps/appCodeFiles.test.js +8 -0
- package/dist/handlers/apps/appsDownload.d.ts +1 -1
- package/dist/handlers/apps/appsDownload.d.ts.map +1 -1
- package/dist/handlers/apps/appsDownload.js +2 -2
- package/dist/handlers/apps/createApp.d.ts.map +1 -1
- package/dist/handlers/apps/createApp.js +8 -6
- package/dist/handlers/apps/createApp.test.js +21 -2
- package/dist/handlers/apps/preview.d.ts +12 -0
- package/dist/handlers/apps/preview.d.ts.map +1 -1
- package/dist/handlers/apps/preview.js +120 -12
- package/dist/handlers/apps/preview.test.js +70 -1
- package/dist/handlers/download.d.ts.map +1 -1
- package/dist/handlers/download.js +3 -1
- package/dist/index.js +4 -2
- package/package.json +3 -3
|
@@ -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,
|
|
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
|
|
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: (
|
|
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":"AAAA,OAAO,EAIH,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,0BAA0B,cACxB,MAAM,EAAE,KACpB,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,KACrB;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,
|
|
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 = (
|
|
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 ${
|
|
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,
|
|
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
|
-
|
|
190
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":"
|
|
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
|
|
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
|
-
|
|
105
|
-
|
|
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.
|
|
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(`
|
|
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(
|
|
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', [
|
|
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
|
|
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":"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
|
|
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(
|
|
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
|
|
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
|
|
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.
|
|
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/
|
|
45
|
-
"@lightdash/
|
|
44
|
+
"@lightdash/common": "1.78.0",
|
|
45
|
+
"@lightdash/warehouses": "1.78.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/inquirer": "8.2.4",
|