@lightdash/cli 1.105.0 → 1.107.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/preview.d.ts +10 -0
- package/dist/handlers/apps/preview.d.ts.map +1 -1
- package/dist/handlers/apps/preview.js +69 -1
- package/dist/handlers/apps/preview.test.js +86 -0
- package/dist/vendor/template/references/external-apis.md +3 -0
- package/dist/vendor/template/vite.config.js +22 -5
- package/package.json +3 -3
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DataAppManifest } from '@lightdash/common';
|
|
1
2
|
/**
|
|
2
3
|
* Environment passed to the `npm run dev` child process. Only the small set of
|
|
3
4
|
* host variables needed to launch a portable child process is inherited. In
|
|
@@ -10,8 +11,17 @@ export declare const buildPreviewChildEnv: (args: {
|
|
|
10
11
|
projectUuid: string;
|
|
11
12
|
proxyPort: number;
|
|
12
13
|
proxyNonce: string;
|
|
14
|
+
browserImageOrigins?: string[];
|
|
13
15
|
parentEnv?: NodeJS.ProcessEnv;
|
|
14
16
|
}) => Record<string, string>;
|
|
17
|
+
export declare const fetchBrowserImageOrigins: (args: {
|
|
18
|
+
manifest: DataAppManifest;
|
|
19
|
+
projectUuid: string;
|
|
20
|
+
serverUrl: string;
|
|
21
|
+
authorization: string;
|
|
22
|
+
proxyAuthorization?: string;
|
|
23
|
+
fetchFn?: typeof fetch;
|
|
24
|
+
}) => Promise<string[]>;
|
|
15
25
|
/**
|
|
16
26
|
* Older downloads have a vite.config.js that proxies /api straight to the
|
|
17
27
|
* instance and expects the credential in .env.local — incompatible with the
|
|
@@ -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":"AAAA,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAc3B;;;;;;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,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CA8CxB,CAAC;AAEF,eAAO,MAAM,wBAAwB,SAAgB;IACjD,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,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,MAAM,EAAE,CA6EnB,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,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CA2BlD,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,CA2Id,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.appsPreviewHandler = exports.resolvePreviewPort = exports.removeLegacyPreviewCredential = exports.preflightPreviewRequest = exports.projectNotFoundMessage = exports.ensureNodeModules = 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.fetchBrowserImageOrigins = 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");
|
|
@@ -64,9 +64,68 @@ const buildPreviewChildEnv = (args) => {
|
|
|
64
64
|
VITE_LIGHTDASH_PROJECT_UUID: args.projectUuid,
|
|
65
65
|
LIGHTDASH_PREVIEW_PROXY_TARGET: `http://127.0.0.1:${args.proxyPort}`,
|
|
66
66
|
LIGHTDASH_PREVIEW_PROXY_NONCE: args.proxyNonce,
|
|
67
|
+
LIGHTDASH_PREVIEW_BROWSER_IMAGE_ORIGINS: JSON.stringify(args.browserImageOrigins ?? []),
|
|
67
68
|
};
|
|
68
69
|
};
|
|
69
70
|
exports.buildPreviewChildEnv = buildPreviewChildEnv;
|
|
71
|
+
const fetchBrowserImageOrigins = async (args) => {
|
|
72
|
+
const linkedSlugs = new Set((args.manifest.externalConnections ?? []).map(({ connectionSlug }) => connectionSlug));
|
|
73
|
+
if (linkedSlugs.size === 0)
|
|
74
|
+
return [];
|
|
75
|
+
const response = await (args.fetchFn ?? fetch)(new URL(`/api/v1/ee/projects/${args.projectUuid}/external-connections`, args.serverUrl), {
|
|
76
|
+
headers: {
|
|
77
|
+
Authorization: args.authorization,
|
|
78
|
+
...(args.proxyAuthorization
|
|
79
|
+
? { 'Proxy-Authorization': args.proxyAuthorization }
|
|
80
|
+
: {}),
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw new Error(`Could not resolve browser image origins for local preview (${response.status}).`);
|
|
85
|
+
}
|
|
86
|
+
const payload = await response.json();
|
|
87
|
+
if (typeof payload !== 'object' ||
|
|
88
|
+
payload === null ||
|
|
89
|
+
!('results' in payload) ||
|
|
90
|
+
!Array.isArray(payload.results)) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
return [
|
|
94
|
+
...new Set(payload.results.flatMap((connection) => {
|
|
95
|
+
if (typeof connection !== 'object' ||
|
|
96
|
+
connection === null ||
|
|
97
|
+
!('slug' in connection) ||
|
|
98
|
+
typeof connection.slug !== 'string' ||
|
|
99
|
+
!linkedSlugs.has(connection.slug) ||
|
|
100
|
+
!('allowBrowserImages' in connection) ||
|
|
101
|
+
connection.allowBrowserImages !== true ||
|
|
102
|
+
!('type' in connection) ||
|
|
103
|
+
connection.type !== 'none' ||
|
|
104
|
+
!('origin' in connection) ||
|
|
105
|
+
typeof connection.origin !== 'string') {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
let originUrl;
|
|
109
|
+
try {
|
|
110
|
+
originUrl = new URL(connection.origin);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
if (originUrl.protocol !== 'https:' ||
|
|
116
|
+
originUrl.username ||
|
|
117
|
+
originUrl.password ||
|
|
118
|
+
(originUrl.pathname && originUrl.pathname !== '/') ||
|
|
119
|
+
originUrl.search ||
|
|
120
|
+
originUrl.hash ||
|
|
121
|
+
!originUrl.hostname) {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
return [originUrl.origin];
|
|
125
|
+
})),
|
|
126
|
+
].sort();
|
|
127
|
+
};
|
|
128
|
+
exports.fetchBrowserImageOrigins = fetchBrowserImageOrigins;
|
|
70
129
|
/**
|
|
71
130
|
* Older downloads have a vite.config.js that proxies /api straight to the
|
|
72
131
|
* instance and expects the credential in .env.local — incompatible with the
|
|
@@ -297,6 +356,7 @@ const appsPreviewHandler = async (pathArg, options) => {
|
|
|
297
356
|
currentProjectUuid: config.context?.project,
|
|
298
357
|
cwd: process.cwd(),
|
|
299
358
|
});
|
|
359
|
+
const manifest = await (0, appCodeFiles_1.readManifestFromDir)(target.appDir);
|
|
300
360
|
await (0, exports.ensureNodeModules)({
|
|
301
361
|
appDir: target.appDir,
|
|
302
362
|
assumeYes: options.assumeYes,
|
|
@@ -324,6 +384,13 @@ const appsPreviewHandler = async (pathArg, options) => {
|
|
|
324
384
|
serverUrl,
|
|
325
385
|
}));
|
|
326
386
|
}
|
|
387
|
+
const browserImageOrigins = await (0, exports.fetchBrowserImageOrigins)({
|
|
388
|
+
manifest,
|
|
389
|
+
projectUuid: target.projectUuid,
|
|
390
|
+
serverUrl,
|
|
391
|
+
authorization,
|
|
392
|
+
proxyAuthorization,
|
|
393
|
+
});
|
|
327
394
|
// Previous versions persisted this credential in .env.local. Remove only
|
|
328
395
|
// that obsolete entry, preserving any unrelated user-managed settings.
|
|
329
396
|
if (await (0, exports.removeLegacyPreviewCredential)(target.appDir)) {
|
|
@@ -358,6 +425,7 @@ const appsPreviewHandler = async (pathArg, options) => {
|
|
|
358
425
|
projectUuid: target.projectUuid,
|
|
359
426
|
proxyPort: proxy.port,
|
|
360
427
|
proxyNonce,
|
|
428
|
+
browserImageOrigins,
|
|
361
429
|
}),
|
|
362
430
|
});
|
|
363
431
|
}
|
|
@@ -40,6 +40,7 @@ describe('buildPreviewChildEnv', () => {
|
|
|
40
40
|
projectUuid: 'proj-uuid-1',
|
|
41
41
|
proxyPort: 45678,
|
|
42
42
|
proxyNonce: 'nonce-abc',
|
|
43
|
+
browserImageOrigins: ['https://tiles.example.com'],
|
|
43
44
|
parentEnv: {
|
|
44
45
|
HOME: '/home/developer',
|
|
45
46
|
PATH: '/usr/bin',
|
|
@@ -57,6 +58,7 @@ describe('buildPreviewChildEnv', () => {
|
|
|
57
58
|
VITE_LIGHTDASH_PROJECT_UUID: 'proj-uuid-1',
|
|
58
59
|
LIGHTDASH_PREVIEW_PROXY_TARGET: 'http://127.0.0.1:45678',
|
|
59
60
|
LIGHTDASH_PREVIEW_PROXY_NONCE: 'nonce-abc',
|
|
61
|
+
LIGHTDASH_PREVIEW_BROWSER_IMAGE_ORIGINS: '["https://tiles.example.com"]',
|
|
60
62
|
});
|
|
61
63
|
expect(env).not.toHaveProperty('LIGHTDASH_API_KEY');
|
|
62
64
|
expect(env).not.toHaveProperty('LIGHTDASH_PROXY_AUTHORIZATION');
|
|
@@ -75,6 +77,90 @@ describe('buildPreviewChildEnv', () => {
|
|
|
75
77
|
expect(env.VITE_LIGHTDASH_URL).toBe('http://localhost:3000');
|
|
76
78
|
});
|
|
77
79
|
});
|
|
80
|
+
describe('fetchBrowserImageOrigins', () => {
|
|
81
|
+
it('returns opted-in no-auth origins linked by manifest slug', async () => {
|
|
82
|
+
const connection = {
|
|
83
|
+
slug: 'public-tiles',
|
|
84
|
+
type: 'none',
|
|
85
|
+
origin: 'https://tiles.example.com',
|
|
86
|
+
allowBrowserImages: true,
|
|
87
|
+
};
|
|
88
|
+
const origins = await (0, preview_1.fetchBrowserImageOrigins)({
|
|
89
|
+
manifest: {
|
|
90
|
+
...previewBundle.manifest,
|
|
91
|
+
externalConnections: [
|
|
92
|
+
{ alias: 'tiles', connectionSlug: 'public-tiles' },
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
projectUuid: 'proj-uuid-1',
|
|
96
|
+
serverUrl: 'https://lightdash.example.com',
|
|
97
|
+
authorization: 'ApiKey token',
|
|
98
|
+
fetchFn: vi.fn().mockResolvedValue({
|
|
99
|
+
ok: true,
|
|
100
|
+
json: async () => ({ results: [connection] }),
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
expect(origins).toEqual(['https://tiles.example.com']);
|
|
104
|
+
});
|
|
105
|
+
it('fails closed for malformed response shapes', async () => {
|
|
106
|
+
const origins = await (0, preview_1.fetchBrowserImageOrigins)({
|
|
107
|
+
manifest: {
|
|
108
|
+
...previewBundle.manifest,
|
|
109
|
+
externalConnections: [
|
|
110
|
+
{ alias: 'tiles', connectionSlug: 'public-tiles' },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
projectUuid: 'proj-uuid-1',
|
|
114
|
+
serverUrl: 'https://lightdash.example.com',
|
|
115
|
+
authorization: 'ApiKey token',
|
|
116
|
+
fetchFn: vi.fn().mockResolvedValue({
|
|
117
|
+
ok: true,
|
|
118
|
+
json: async () => ({ results: 'not-an-array' }),
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
121
|
+
expect(origins).toEqual([]);
|
|
122
|
+
});
|
|
123
|
+
it('ignores malformed connections and unsafe origins', async () => {
|
|
124
|
+
const origins = await (0, preview_1.fetchBrowserImageOrigins)({
|
|
125
|
+
manifest: {
|
|
126
|
+
...previewBundle.manifest,
|
|
127
|
+
externalConnections: [
|
|
128
|
+
{ alias: 'tiles', connectionSlug: 'public-tiles' },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
projectUuid: 'proj-uuid-1',
|
|
132
|
+
serverUrl: 'https://lightdash.example.com',
|
|
133
|
+
authorization: 'ApiKey token',
|
|
134
|
+
fetchFn: vi.fn().mockResolvedValue({
|
|
135
|
+
ok: true,
|
|
136
|
+
json: async () => ({
|
|
137
|
+
results: [
|
|
138
|
+
null,
|
|
139
|
+
{
|
|
140
|
+
slug: 'public-tiles',
|
|
141
|
+
type: 'none',
|
|
142
|
+
origin: 'not-a-url',
|
|
143
|
+
allowBrowserImages: true,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
slug: 'public-tiles',
|
|
147
|
+
type: 'none',
|
|
148
|
+
origin: 'https://tiles.example.com/path',
|
|
149
|
+
allowBrowserImages: true,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
slug: 'public-tiles',
|
|
153
|
+
type: 'none',
|
|
154
|
+
origin: 'https://tiles.example.com',
|
|
155
|
+
allowBrowserImages: true,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}),
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
expect(origins).toEqual(['https://tiles.example.com']);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
78
164
|
describe('assertScaffoldingSupportsPreviewProxy', () => {
|
|
79
165
|
it('passes when vite.config.js reads the proxy target', async () => {
|
|
80
166
|
const dir = await fs_1.promises.mkdtemp(path.join(os.tmpdir(), 'ld-prev-'));
|
|
@@ -8,6 +8,7 @@ Each file documents one connection:
|
|
|
8
8
|
- `instructions` — admin-authored notes on how to use this API (auth quirks, pagination, which endpoints matter, response caveats). Present only when the admin wrote them; when present, read and follow them.
|
|
9
9
|
- `signature` / `howToCall` — the exact typed SDK call. Auth is injected by Lightdash — never include credentials or API keys.
|
|
10
10
|
- `origin` / `requestUrl` — the connection's base origin (host only) and how the URL is formed: **the full request URL is `origin + path`.** Your `path` is appended to the origin verbatim — the origin and the path prefix are NOT auto-prepended.
|
|
11
|
+
- `browserImageOrigin` — when non-null, the app may load public images directly from this exact origin in `<img>`, CSS image URLs, canvas-compatible image loaders, or map tile layers such as Leaflet. This is an image-rendering exception only: keep API/data calls on `externalFetch`, and never put Lightdash data or secrets in an image URL.
|
|
11
12
|
- `rules` — hard requirements. The big ones: (1) **`path` is the COMPLETE path from the origin** — pass the whole path (e.g. `/repos/owner/repo/issues`, never a shortened `/issues`) and make sure it starts with one of `allowedPathPrefixes`. (2) **`query` is `Record<string, string>` — every query value MUST be a string** (`{ latitude: '52.52' }`, never `{ latitude: 52.52 }`); numbers and booleans are rejected with a 422. Read the response from `result.body`.
|
|
12
13
|
- `allowedMethods` / `allowedPathPrefixes` — the methods and path prefixes the admin has permitted; only call within these bounds.
|
|
13
14
|
- `samples` — example `{ request, response }` pairs. Copy the request shape — including the FULL `request.path` — when building your `externalFetch` calls. Treat response values as illustrative of shape, not exhaustive.
|
|
@@ -43,6 +44,8 @@ credentials, makes the request server-side, and returns the response.
|
|
|
43
44
|
- **Always** use `lightdash.externalFetch()` for external data. **Never** use
|
|
44
45
|
raw `fetch()`, `XMLHttpRequest`, `axios`, or any other client to call an
|
|
45
46
|
external API directly — those calls are blocked by the sandbox and will fail.
|
|
47
|
+
The only exception is image rendering from a connection whose doc has a
|
|
48
|
+
non-null `browserImageOrigin`; use the exact origin shown there.
|
|
46
49
|
- **Never** hardcode API keys, tokens, passwords, or any secret in the app.
|
|
47
50
|
The connection holds the credentials; the app holds only the alias.
|
|
48
51
|
- **Never** ask the user for an API key or secret, and never add an input field
|
|
@@ -88,7 +88,8 @@ function annotateJsx(code, filename, relPath) {
|
|
|
88
88
|
for (const node of targets) {
|
|
89
89
|
const line = offsetToLine(lineIdx, node.start);
|
|
90
90
|
const insertion = ` data-loc="${relPath}:${line}"`;
|
|
91
|
-
out =
|
|
91
|
+
out =
|
|
92
|
+
out.slice(0, node.name.end) + insertion + out.slice(node.name.end);
|
|
92
93
|
}
|
|
93
94
|
return out;
|
|
94
95
|
}
|
|
@@ -132,9 +133,7 @@ function jsxSourceLocVitePlugin() {
|
|
|
132
133
|
// an opinion-free `code`.
|
|
133
134
|
if (!/<[A-Za-z]/.test(code)) return null;
|
|
134
135
|
|
|
135
|
-
const relPath = path
|
|
136
|
-
.relative(cwd, filename)
|
|
137
|
-
.replace(/\\/g, '/');
|
|
136
|
+
const relPath = path.relative(cwd, filename).replace(/\\/g, '/');
|
|
138
137
|
const annotated = annotateJsx(code, filename, relPath);
|
|
139
138
|
return annotated ?? code;
|
|
140
139
|
},
|
|
@@ -152,6 +151,24 @@ export default defineConfig(({ mode }) => {
|
|
|
152
151
|
const env = loadEnv(mode, process.cwd(), ['VITE_', 'LIGHTDASH_PREVIEW_']);
|
|
153
152
|
const previewProxyTarget = env.LIGHTDASH_PREVIEW_PROXY_TARGET;
|
|
154
153
|
const previewProxyNonce = env.LIGHTDASH_PREVIEW_PROXY_NONCE;
|
|
154
|
+
let browserImageOrigins = [];
|
|
155
|
+
try {
|
|
156
|
+
const parsed = JSON.parse(
|
|
157
|
+
env.LIGHTDASH_PREVIEW_BROWSER_IMAGE_ORIGINS || '[]',
|
|
158
|
+
);
|
|
159
|
+
browserImageOrigins = Array.isArray(parsed)
|
|
160
|
+
? parsed.filter((origin) => {
|
|
161
|
+
try {
|
|
162
|
+
const url = new URL(origin);
|
|
163
|
+
return url.protocol === 'https:' && url.origin === origin;
|
|
164
|
+
} catch {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
: [];
|
|
169
|
+
} catch {
|
|
170
|
+
browserImageOrigins = [];
|
|
171
|
+
}
|
|
155
172
|
const lightdashUrl =
|
|
156
173
|
env.VITE_LIGHTDASH_URL || 'https://app.lightdash.cloud';
|
|
157
174
|
|
|
@@ -165,7 +182,7 @@ export default defineConfig(({ mode }) => {
|
|
|
165
182
|
`script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:`,
|
|
166
183
|
`style-src 'self' 'unsafe-inline'`,
|
|
167
184
|
`connect-src 'self'`,
|
|
168
|
-
`img-src 'self' data: blob
|
|
185
|
+
`img-src 'self' data: blob: ${browserImageOrigins.join(' ')}`,
|
|
169
186
|
`font-src 'self' data:`,
|
|
170
187
|
`worker-src 'self' blob:`,
|
|
171
188
|
`child-src 'self' blob:`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.107.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/common": "1.
|
|
45
|
-
"@lightdash/warehouses": "1.
|
|
44
|
+
"@lightdash/common": "1.107.0",
|
|
45
|
+
"@lightdash/warehouses": "1.107.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/inquirer": "8.2.4",
|