@embeddable.com/sdk-core 4.3.3-next.0 → 4.4.0-next.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/lib/defineConfig.d.ts +6 -0
- package/lib/index.esm.js +34 -6
- package/lib/index.esm.js.map +1 -1
- package/lib/push.d.ts +1 -0
- package/package.json +1 -1
- package/src/defineConfig.test.ts +1 -0
- package/src/defineConfig.ts +5 -0
- package/src/dev.test.ts +121 -2
- package/src/dev.ts +27 -3
- package/src/push.test.ts +116 -3
- package/src/push.ts +18 -2
package/lib/push.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ResolvedEmbeddableConfig } from "./defineConfig";
|
|
|
3
3
|
export declare const CUBE_FILES: RegExp;
|
|
4
4
|
export declare const CLIENT_CONTEXT_FILES: RegExp;
|
|
5
5
|
export declare const SECURITY_CONTEXT_FILES: RegExp;
|
|
6
|
+
export declare const EMBEDDABLE_FILES: RegExp;
|
|
6
7
|
declare const _default: () => Promise<void>;
|
|
7
8
|
export default _default;
|
|
8
9
|
export declare function buildArchive(config: ResolvedEmbeddableConfig): Promise<Ora>;
|
package/package.json
CHANGED
package/src/defineConfig.test.ts
CHANGED
package/src/defineConfig.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type EmbeddableConfig = {
|
|
|
19
19
|
})[];
|
|
20
20
|
pushModels?: boolean;
|
|
21
21
|
pushComponents?: boolean;
|
|
22
|
+
pushEmbeddables?: boolean;
|
|
22
23
|
pushBaseUrl?: string;
|
|
23
24
|
audienceUrl?: string;
|
|
24
25
|
authDomain?: string;
|
|
@@ -83,6 +84,7 @@ export type ResolvedEmbeddableConfig = {
|
|
|
83
84
|
};
|
|
84
85
|
pushModels: boolean;
|
|
85
86
|
pushComponents: boolean;
|
|
87
|
+
pushEmbeddables: boolean;
|
|
86
88
|
pushBaseUrl: string;
|
|
87
89
|
audienceUrl: string;
|
|
88
90
|
previewBaseUrl: string;
|
|
@@ -152,6 +154,7 @@ export const embeddableConfigSchema = z
|
|
|
152
154
|
).optional(),
|
|
153
155
|
pushModels: z.boolean().optional(),
|
|
154
156
|
pushComponents: z.boolean().optional(),
|
|
157
|
+
pushEmbeddables: z.boolean().optional(),
|
|
155
158
|
pushBaseUrl: z.string().optional(),
|
|
156
159
|
audienceUrl: z.string().optional(),
|
|
157
160
|
authDomain: z.string().optional(),
|
|
@@ -202,6 +205,7 @@ export default (config: EmbeddableConfig) => {
|
|
|
202
205
|
pushModels = true,
|
|
203
206
|
starterEmbeddables,
|
|
204
207
|
pushComponents = true,
|
|
208
|
+
pushEmbeddables = true,
|
|
205
209
|
pushBaseUrl,
|
|
206
210
|
audienceUrl,
|
|
207
211
|
authDomain,
|
|
@@ -308,6 +312,7 @@ export default (config: EmbeddableConfig) => {
|
|
|
308
312
|
starterEmbeddables,
|
|
309
313
|
pushModels,
|
|
310
314
|
pushComponents,
|
|
315
|
+
pushEmbeddables,
|
|
311
316
|
pushBaseUrl: pushBaseUrl ?? regionConfig.pushBaseUrl,
|
|
312
317
|
audienceUrl: audienceUrl ?? regionConfig.audienceUrl,
|
|
313
318
|
previewBaseUrl: previewBaseUrl ?? regionConfig.previewBaseUrl,
|
package/src/dev.test.ts
CHANGED
|
@@ -29,7 +29,8 @@ import { logError } from "./logger";
|
|
|
29
29
|
import { ResolvedEmbeddableConfig } from "./defineConfig";
|
|
30
30
|
import { RollupWatcher } from "rollup";
|
|
31
31
|
import ora from "ora";
|
|
32
|
-
import { archive } from "./push";
|
|
32
|
+
import { archive, EMBEDDABLE_FILES } from "./push";
|
|
33
|
+
import fg from "fast-glob";
|
|
33
34
|
import { selectWorkspace } from "./workspaceUtils";
|
|
34
35
|
import serveStatic from "serve-static";
|
|
35
36
|
import { createNodeSys } from "@stencil/core/sys/node";
|
|
@@ -107,6 +108,8 @@ vi.mock("serve-static", () => ({
|
|
|
107
108
|
default: vi.fn(() => vi.fn()),
|
|
108
109
|
}));
|
|
109
110
|
|
|
111
|
+
vi.mock("fast-glob", () => ({ default: vi.fn() }));
|
|
112
|
+
|
|
110
113
|
vi.mock("./dev", async (importOriginal) => {
|
|
111
114
|
const actual = await importOriginal<typeof dev>();
|
|
112
115
|
return {
|
|
@@ -221,6 +224,8 @@ describe("dev command", () => {
|
|
|
221
224
|
["mock-model.json", "/mock/root/models/mock-model.json"],
|
|
222
225
|
]);
|
|
223
226
|
|
|
227
|
+
vi.mocked(fg).mockResolvedValue([]);
|
|
228
|
+
|
|
224
229
|
// Mock fs functions
|
|
225
230
|
vi.mocked(fs.readFile).mockResolvedValue("default content");
|
|
226
231
|
vi.mocked(fs.appendFile).mockResolvedValue(undefined);
|
|
@@ -417,6 +422,49 @@ describe("dev command", () => {
|
|
|
417
422
|
isDev: true,
|
|
418
423
|
});
|
|
419
424
|
});
|
|
425
|
+
|
|
426
|
+
it("should include embeddable files in archive when pushEmbeddables is true", async () => {
|
|
427
|
+
const embeddableConfig = {
|
|
428
|
+
...mockConfig,
|
|
429
|
+
pushEmbeddables: true,
|
|
430
|
+
client: { ...mockConfig.client, srcDir: "/mock/src" },
|
|
431
|
+
} as unknown as ResolvedEmbeddableConfig;
|
|
432
|
+
|
|
433
|
+
vi.mocked(findFiles).mockImplementation(async (_dir, pattern) => {
|
|
434
|
+
if (pattern === EMBEDDABLE_FILES) {
|
|
435
|
+
return [["dashboard.embeddable.yaml", "/mock/src/dashboard.embeddable.yaml"]];
|
|
436
|
+
}
|
|
437
|
+
return [["mock-model.json", "/mock/root/models/mock-model.json"]];
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
await sendBuildChanges(embeddableConfig);
|
|
441
|
+
|
|
442
|
+
expect(findFiles).toHaveBeenCalledWith("/mock/src", EMBEDDABLE_FILES);
|
|
443
|
+
expect(archive).toHaveBeenCalledWith(
|
|
444
|
+
expect.objectContaining({
|
|
445
|
+
filesList: expect.arrayContaining([
|
|
446
|
+
["dashboard.embeddable.yaml", "/mock/src/dashboard.embeddable.yaml"],
|
|
447
|
+
]),
|
|
448
|
+
}),
|
|
449
|
+
);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it("should not call findFiles with EMBEDDABLE_FILES when pushEmbeddables is false", async () => {
|
|
453
|
+
const embeddableConfig = {
|
|
454
|
+
...mockConfig,
|
|
455
|
+
pushEmbeddables: false,
|
|
456
|
+
client: { ...mockConfig.client, srcDir: "/mock/src" },
|
|
457
|
+
} as unknown as ResolvedEmbeddableConfig;
|
|
458
|
+
|
|
459
|
+
vi.mocked(findFiles).mockClear();
|
|
460
|
+
|
|
461
|
+
await sendBuildChanges(embeddableConfig);
|
|
462
|
+
|
|
463
|
+
const embeddableFilesCall = vi.mocked(findFiles).mock.calls.find(
|
|
464
|
+
(call) => call[1] === EMBEDDABLE_FILES,
|
|
465
|
+
);
|
|
466
|
+
expect(embeddableFilesCall).toBeUndefined();
|
|
467
|
+
});
|
|
420
468
|
});
|
|
421
469
|
|
|
422
470
|
describe("sendBuildChanges error handling", () => {
|
|
@@ -439,7 +487,7 @@ describe("dev command", () => {
|
|
|
439
487
|
await sendBuildChanges(mockConfig as unknown as ResolvedEmbeddableConfig);
|
|
440
488
|
|
|
441
489
|
expect(ora().fail).toHaveBeenCalledWith(
|
|
442
|
-
`Data models and/or security context synchronization failed with error: ${error.message}`,
|
|
490
|
+
`Data models and/or security context and/or embeddables synchronization failed with error: ${error.message}`,
|
|
443
491
|
);
|
|
444
492
|
expect(mockWss.clients[0].send).toHaveBeenCalledWith(
|
|
445
493
|
JSON.stringify({ type: "dataModelsAndOrSecurityContextUpdateError", error: error.message }),
|
|
@@ -447,6 +495,77 @@ describe("dev command", () => {
|
|
|
447
495
|
});
|
|
448
496
|
});
|
|
449
497
|
|
|
498
|
+
describe("cubeSecurityContextAndClientContextWatcher (pushEmbeddables)", () => {
|
|
499
|
+
it("should call fg with embeddable pattern and pass results to chokidar.watch when pushEmbeddables is true", async () => {
|
|
500
|
+
const mockEmbeddableFiles = [
|
|
501
|
+
"/mock/src/dashboard.embeddable.yaml",
|
|
502
|
+
"/mock/src/report.embeddable.yml",
|
|
503
|
+
];
|
|
504
|
+
|
|
505
|
+
vi.mocked(fg).mockImplementation(async (pattern: any) => {
|
|
506
|
+
if (pattern === "**/*.embeddable.{yaml,yml}") {
|
|
507
|
+
return mockEmbeddableFiles as any;
|
|
508
|
+
}
|
|
509
|
+
return [];
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
513
|
+
...mockConfig,
|
|
514
|
+
pushEmbeddables: true,
|
|
515
|
+
client: { ...mockConfig.client, srcDir: "/mock/src" },
|
|
516
|
+
} as unknown as ResolvedEmbeddableConfig);
|
|
517
|
+
|
|
518
|
+
await dev();
|
|
519
|
+
await listenMock.mock.calls[0][1]();
|
|
520
|
+
|
|
521
|
+
expect(vi.mocked(fg)).toHaveBeenCalledWith(
|
|
522
|
+
"**/*.embeddable.{yaml,yml}",
|
|
523
|
+
expect.objectContaining({ cwd: "/mock/src", absolute: true }),
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
expect(chokidar.watch).toHaveBeenCalledWith(
|
|
527
|
+
expect.arrayContaining(mockEmbeddableFiles),
|
|
528
|
+
expect.anything(),
|
|
529
|
+
);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it("should not call fg with embeddable pattern when pushEmbeddables is false", async () => {
|
|
533
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
534
|
+
...mockConfig,
|
|
535
|
+
pushEmbeddables: false,
|
|
536
|
+
client: { ...mockConfig.client, srcDir: "/mock/src" },
|
|
537
|
+
} as unknown as ResolvedEmbeddableConfig);
|
|
538
|
+
|
|
539
|
+
vi.mocked(fg).mockClear();
|
|
540
|
+
|
|
541
|
+
await dev();
|
|
542
|
+
await listenMock.mock.calls[0][1]();
|
|
543
|
+
|
|
544
|
+
const embeddableCall = vi.mocked(fg).mock.calls.find(
|
|
545
|
+
(call) => call[0] === "**/*.embeddable.{yaml,yml}",
|
|
546
|
+
);
|
|
547
|
+
expect(embeddableCall).toBeUndefined();
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it("should not call fg with embeddable pattern when pushEmbeddables is undefined", async () => {
|
|
551
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
552
|
+
...mockConfig,
|
|
553
|
+
// pushEmbeddables not set → undefined → falsy
|
|
554
|
+
client: { ...mockConfig.client, srcDir: "/mock/src" },
|
|
555
|
+
} as unknown as ResolvedEmbeddableConfig);
|
|
556
|
+
|
|
557
|
+
vi.mocked(fg).mockClear();
|
|
558
|
+
|
|
559
|
+
await dev();
|
|
560
|
+
await listenMock.mock.calls[0][1]();
|
|
561
|
+
|
|
562
|
+
const embeddableCall = vi.mocked(fg).mock.calls.find(
|
|
563
|
+
(call) => call[0] === "**/*.embeddable.{yaml,yml}",
|
|
564
|
+
);
|
|
565
|
+
expect(embeddableCall).toBeUndefined();
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
450
569
|
describe("Plugin build coordination", () => {
|
|
451
570
|
it("should handle configs with no plugins when pushComponents is true", async () => {
|
|
452
571
|
vi.mocked(provideConfig).mockResolvedValue({
|
package/src/dev.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
sendBuild,
|
|
29
29
|
SECURITY_CONTEXT_FILES,
|
|
30
30
|
CLIENT_CONTEXT_FILES,
|
|
31
|
+
EMBEDDABLE_FILES,
|
|
31
32
|
} from "./push";
|
|
32
33
|
import validate from "./validate";
|
|
33
34
|
import { checkNodeVersion } from "./utils";
|
|
@@ -494,6 +495,14 @@ const cubeSecurityContextAndClientContextWatcher = async (
|
|
|
494
495
|
filesToWatch = [...filesToWatch, ...cubeFiles, ...securityContextFiles];
|
|
495
496
|
}
|
|
496
497
|
|
|
498
|
+
if (ctx.pushEmbeddables) {
|
|
499
|
+
const embeddableFiles = await fg("**/*.embeddable.{yaml,yml}", {
|
|
500
|
+
cwd: ctx.client.srcDir,
|
|
501
|
+
absolute: true,
|
|
502
|
+
});
|
|
503
|
+
filesToWatch = [...filesToWatch, ...embeddableFiles];
|
|
504
|
+
}
|
|
505
|
+
|
|
497
506
|
const fsWatcher = chokidar.watch(filesToWatch, chokidarWatchOptions);
|
|
498
507
|
|
|
499
508
|
fsWatcher.on("all", () => sendBuildChanges(ctx));
|
|
@@ -526,7 +535,7 @@ export const sendBuildChanges = async (ctx: ResolvedEmbeddableConfig) => {
|
|
|
526
535
|
sendMessage("dataModelsAndOrSecurityContextUpdateStart");
|
|
527
536
|
|
|
528
537
|
const sending = ora(
|
|
529
|
-
"Synchronising data models and/or security contexts...",
|
|
538
|
+
"Synchronising data models and/or security contexts and/or embeddables...",
|
|
530
539
|
).start();
|
|
531
540
|
|
|
532
541
|
let filesList: [string, string][] = [];
|
|
@@ -567,6 +576,21 @@ export const sendBuildChanges = async (ctx: ResolvedEmbeddableConfig) => {
|
|
|
567
576
|
filesList = [...filesList, ...cubeAndSecurityContextFileList];
|
|
568
577
|
}
|
|
569
578
|
|
|
579
|
+
if (ctx.pushEmbeddables) {
|
|
580
|
+
const embeddableFilesList = await findFiles(
|
|
581
|
+
ctx.client.srcDir,
|
|
582
|
+
EMBEDDABLE_FILES,
|
|
583
|
+
);
|
|
584
|
+
|
|
585
|
+
filesList = [
|
|
586
|
+
...filesList,
|
|
587
|
+
...embeddableFilesList.map((entry): [string, string] => [
|
|
588
|
+
path.basename(entry[1]),
|
|
589
|
+
entry[1],
|
|
590
|
+
]),
|
|
591
|
+
];
|
|
592
|
+
}
|
|
593
|
+
|
|
570
594
|
try {
|
|
571
595
|
const token = await getToken();
|
|
572
596
|
await archive({
|
|
@@ -578,12 +602,12 @@ export const sendBuildChanges = async (ctx: ResolvedEmbeddableConfig) => {
|
|
|
578
602
|
} catch (e: any) {
|
|
579
603
|
const errorMessage = e.response?.data?.errorMessage ?? e.message ?? "Unknown error";
|
|
580
604
|
sending.fail(
|
|
581
|
-
`Data models and/or security context synchronization failed with error: ${errorMessage}`,
|
|
605
|
+
`Data models and/or security context and/or embeddables synchronization failed with error: ${errorMessage}`,
|
|
582
606
|
);
|
|
583
607
|
return sendMessage("dataModelsAndOrSecurityContextUpdateError", { error: errorMessage });
|
|
584
608
|
}
|
|
585
609
|
|
|
586
|
-
sending.succeed(`Data models and/or security context synchronized`);
|
|
610
|
+
sending.succeed(`Data models and/or security context and/or embeddables synchronized`);
|
|
587
611
|
sendMessage("dataModelsAndOrSecurityContextUpdateSuccess");
|
|
588
612
|
};
|
|
589
613
|
|
package/src/push.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import push, { buildArchive } from "./push";
|
|
1
|
+
import push, { buildArchive, EMBEDDABLE_FILES } from "./push";
|
|
2
2
|
import provideConfig from "./provideConfig";
|
|
3
3
|
import { fileFromPath } from "formdata-node/file-from-path";
|
|
4
4
|
import * as path from "path";
|
|
@@ -222,22 +222,24 @@ describe("push", () => {
|
|
|
222
222
|
});
|
|
223
223
|
|
|
224
224
|
describe("push configuration", () => {
|
|
225
|
-
it("should fail if
|
|
225
|
+
it("should fail if pushModels, pushComponents, and pushEmbeddables are all disabled", async () => {
|
|
226
226
|
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
227
227
|
vi.mocked(provideConfig).mockResolvedValue({
|
|
228
228
|
...config,
|
|
229
229
|
pushModels: false,
|
|
230
230
|
pushComponents: false,
|
|
231
|
+
pushEmbeddables: false,
|
|
231
232
|
} as ResolvedEmbeddableConfig);
|
|
232
233
|
|
|
233
234
|
await push();
|
|
234
235
|
|
|
235
236
|
expect(startMock.fail).toHaveBeenCalledWith(
|
|
236
|
-
"Cannot push:
|
|
237
|
+
"Cannot push: pushModels, pushComponents, and pushEmbeddables are all disabled"
|
|
237
238
|
);
|
|
238
239
|
expect(process.exit).toHaveBeenCalledWith(1);
|
|
239
240
|
});
|
|
240
241
|
|
|
242
|
+
|
|
241
243
|
it("should only include component files when pushModels is false", async () => {
|
|
242
244
|
const localZipMock = {
|
|
243
245
|
addFile: vi.fn(),
|
|
@@ -633,5 +635,116 @@ describe("push", () => {
|
|
|
633
635
|
expect(findFiles).toHaveBeenCalledWith("/src", expect.any(RegExp));
|
|
634
636
|
expect(findFiles).toHaveBeenCalledWith("/src", expect.any(RegExp));
|
|
635
637
|
});
|
|
638
|
+
|
|
639
|
+
it("should include embeddable files when pushEmbeddables is true", async () => {
|
|
640
|
+
vi.mocked(findFiles)
|
|
641
|
+
.mockResolvedValueOnce([]) // cube files
|
|
642
|
+
.mockResolvedValueOnce([]) // security context files
|
|
643
|
+
.mockResolvedValueOnce([]) // client context files
|
|
644
|
+
.mockResolvedValueOnce([
|
|
645
|
+
["dashboard.embeddable.yaml", "/src/dashboard.embeddable.yaml"],
|
|
646
|
+
["report.embeddable.yml", "/src/report.embeddable.yml"],
|
|
647
|
+
]); // embeddable files
|
|
648
|
+
|
|
649
|
+
const testConfig = {
|
|
650
|
+
...config,
|
|
651
|
+
pushModels: true,
|
|
652
|
+
pushComponents: true,
|
|
653
|
+
pushEmbeddables: true,
|
|
654
|
+
client: {
|
|
655
|
+
...config.client,
|
|
656
|
+
srcDir: "/src",
|
|
657
|
+
},
|
|
658
|
+
} as ResolvedEmbeddableConfig;
|
|
659
|
+
|
|
660
|
+
await buildArchive(testConfig);
|
|
661
|
+
|
|
662
|
+
expect(findFiles).toHaveBeenCalledWith("/src", EMBEDDABLE_FILES);
|
|
663
|
+
expect(mockZipLocal.addFile).toHaveBeenCalledWith(
|
|
664
|
+
"/src/dashboard.embeddable.yaml",
|
|
665
|
+
"dashboard.embeddable.yaml",
|
|
666
|
+
expect.objectContaining({ compress: true }),
|
|
667
|
+
);
|
|
668
|
+
expect(mockZipLocal.addFile).toHaveBeenCalledWith(
|
|
669
|
+
"/src/report.embeddable.yml",
|
|
670
|
+
"report.embeddable.yml",
|
|
671
|
+
expect.objectContaining({ compress: true }),
|
|
672
|
+
);
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it("should not search for embeddable files when pushEmbeddables is false", async () => {
|
|
676
|
+
// Reset call history to avoid interference from previous tests
|
|
677
|
+
vi.mocked(findFiles).mockClear();
|
|
678
|
+
|
|
679
|
+
const testConfig = {
|
|
680
|
+
...config,
|
|
681
|
+
pushModels: true,
|
|
682
|
+
pushComponents: true,
|
|
683
|
+
pushEmbeddables: false,
|
|
684
|
+
client: {
|
|
685
|
+
...config.client,
|
|
686
|
+
srcDir: "/src",
|
|
687
|
+
},
|
|
688
|
+
} as ResolvedEmbeddableConfig;
|
|
689
|
+
|
|
690
|
+
await buildArchive(testConfig);
|
|
691
|
+
|
|
692
|
+
// findFiles should have been called for models and components but NOT for embeddable files
|
|
693
|
+
const embeddableFilesCall = vi
|
|
694
|
+
.mocked(findFiles)
|
|
695
|
+
.mock.calls.find((call) => call[1] === EMBEDDABLE_FILES);
|
|
696
|
+
expect(embeddableFilesCall).toBeUndefined();
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it("should exit when all three push flags are disabled", async () => {
|
|
700
|
+
vi.spyOn(process, "exit").mockImplementation(() => null as never);
|
|
701
|
+
|
|
702
|
+
const testConfig = {
|
|
703
|
+
...config,
|
|
704
|
+
pushModels: false,
|
|
705
|
+
pushComponents: false,
|
|
706
|
+
pushEmbeddables: false,
|
|
707
|
+
client: {
|
|
708
|
+
...config.client,
|
|
709
|
+
srcDir: "/src",
|
|
710
|
+
},
|
|
711
|
+
} as ResolvedEmbeddableConfig;
|
|
712
|
+
|
|
713
|
+
await buildArchive(testConfig);
|
|
714
|
+
|
|
715
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
716
|
+
});
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
describe("EMBEDDABLE_FILES", () => {
|
|
720
|
+
it("should match .embeddable.yaml files", () => {
|
|
721
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.embeddable.yaml")).toBe(true);
|
|
722
|
+
expect(EMBEDDABLE_FILES.test("src/dashboards/sales.embeddable.yaml")).toBe(
|
|
723
|
+
true,
|
|
724
|
+
);
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
it("should match .embeddable.yml files", () => {
|
|
728
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.embeddable.yml")).toBe(true);
|
|
729
|
+
expect(EMBEDDABLE_FILES.test("src/widgets/chart.embeddable.yml")).toBe(
|
|
730
|
+
true,
|
|
731
|
+
);
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
it("should not match unrelated yaml files", () => {
|
|
735
|
+
expect(EMBEDDABLE_FILES.test("config.yaml")).toBe(false);
|
|
736
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.cc.yaml")).toBe(false);
|
|
737
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.sc.yaml")).toBe(false);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it("should not match cube files", () => {
|
|
741
|
+
expect(EMBEDDABLE_FILES.test("my-model.cube.yaml")).toBe(false);
|
|
742
|
+
expect(EMBEDDABLE_FILES.test("my-model.cube.yml")).toBe(false);
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
it("should not match non-yaml extensions", () => {
|
|
746
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.embeddable.json")).toBe(false);
|
|
747
|
+
expect(EMBEDDABLE_FILES.test("my-dashboard.embeddable.ts")).toBe(false);
|
|
748
|
+
});
|
|
636
749
|
});
|
|
637
750
|
});
|
package/src/push.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const CUBE_FILES = /^(.*)\.cube\.(ya?ml|js)$/;
|
|
|
21
21
|
|
|
22
22
|
export const CLIENT_CONTEXT_FILES = /^(.*)\.cc\.ya?ml$/;
|
|
23
23
|
export const SECURITY_CONTEXT_FILES = /^(.*)\.sc\.ya?ml$/;
|
|
24
|
+
export const EMBEDDABLE_FILES = /^(.*)\.embeddable\.ya?ml$/;
|
|
24
25
|
|
|
25
26
|
export default async () => {
|
|
26
27
|
await initLogger("push");
|
|
@@ -110,6 +111,7 @@ const publishedSectionFeedback = (
|
|
|
110
111
|
) => {
|
|
111
112
|
config.pushModels && spinnerPushing.succeed("Models published");
|
|
112
113
|
config.pushComponents && spinnerPushing.succeed("Components published");
|
|
114
|
+
config.pushEmbeddables && spinnerPushing.succeed("Embeddables published");
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
async function pushByApiKey(
|
|
@@ -170,9 +172,9 @@ async function verify(ctx: ResolvedEmbeddableConfig) {
|
|
|
170
172
|
export async function buildArchive(config: ResolvedEmbeddableConfig) {
|
|
171
173
|
const spinnerArchive = ora("Building...").start();
|
|
172
174
|
|
|
173
|
-
if (!config.pushModels && !config.pushComponents) {
|
|
175
|
+
if (!config.pushModels && !config.pushComponents && !config.pushEmbeddables) {
|
|
174
176
|
spinnerArchive.fail(
|
|
175
|
-
"Cannot push:
|
|
177
|
+
"Cannot push: pushModels, pushComponents, and pushEmbeddables are all disabled",
|
|
176
178
|
);
|
|
177
179
|
process.exit(1);
|
|
178
180
|
}
|
|
@@ -217,6 +219,20 @@ export async function buildArchive(config: ResolvedEmbeddableConfig) {
|
|
|
217
219
|
);
|
|
218
220
|
}
|
|
219
221
|
|
|
222
|
+
if (config.pushEmbeddables) {
|
|
223
|
+
const embeddableFilesList = await findFiles(
|
|
224
|
+
config.client.srcDir,
|
|
225
|
+
EMBEDDABLE_FILES,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
filesList.push(
|
|
229
|
+
...embeddableFilesList.map((entry): [string, string] => [
|
|
230
|
+
path.basename(entry[1]),
|
|
231
|
+
entry[1],
|
|
232
|
+
]),
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
220
236
|
await archive({
|
|
221
237
|
ctx: config,
|
|
222
238
|
filesList,
|