@embeddable.com/sdk-core 3.13.0-next.2 → 3.13.0-next.4
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 +128 -1
- package/lib/index.esm.js +78 -13
- package/lib/index.esm.js.map +1 -1
- package/lib/push.d.ts +16 -5
- package/package.json +1 -1
- package/src/defineConfig.test.ts +57 -3
- package/src/defineConfig.ts +113 -22
- package/src/dev.ts +6 -1
- package/src/push.test.ts +410 -5
- package/src/push.ts +53 -26
package/src/push.test.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import push from "./push";
|
|
1
|
+
import push, { buildArchive } from "./push";
|
|
2
2
|
import provideConfig from "./provideConfig";
|
|
3
3
|
import { fileFromPath } from "formdata-node/file-from-path";
|
|
4
4
|
import archiver from "archiver";
|
|
5
5
|
import * as fs from "node:fs/promises";
|
|
6
6
|
import * as fsSync from "node:fs";
|
|
7
7
|
import { findFiles } from "@embeddable.com/sdk-utils";
|
|
8
|
+
import { ResolvedEmbeddableConfig } from "./defineConfig";
|
|
9
|
+
import { vi, describe, it, expect, beforeEach } from "vitest";
|
|
10
|
+
import { getArgumentByKey } from "./utils";
|
|
8
11
|
|
|
9
12
|
// @ts-ignore
|
|
10
13
|
import reportErrorToRollbar from "./rollbar.mjs";
|
|
11
|
-
import { checkBuildSuccess, checkNodeVersion
|
|
14
|
+
import { checkBuildSuccess, checkNodeVersion } from "./utils";
|
|
12
15
|
import { server } from "../../../mocks/server";
|
|
13
16
|
import { http, HttpResponse } from "msw";
|
|
14
17
|
|
|
@@ -85,9 +88,11 @@ const config = {
|
|
|
85
88
|
rootDir: "rootDir",
|
|
86
89
|
buildDir: "buildDir",
|
|
87
90
|
archiveFile: "embeddable-build.zip",
|
|
91
|
+
globalCss: "src/global.css",
|
|
88
92
|
},
|
|
89
93
|
pushBaseUrl: "http://localhost:3000",
|
|
90
94
|
previewBaseUrl: "http://localhost:3000",
|
|
95
|
+
pushComponents: true,
|
|
91
96
|
};
|
|
92
97
|
|
|
93
98
|
describe("push", () => {
|
|
@@ -110,7 +115,6 @@ describe("push", () => {
|
|
|
110
115
|
vi.mocked(fs.stat).mockResolvedValue({
|
|
111
116
|
size: 100,
|
|
112
117
|
} as any);
|
|
113
|
-
|
|
114
118
|
vi.mocked(findFiles).mockResolvedValue([["fileName", "filePath"]]);
|
|
115
119
|
vi.mocked(fileFromPath).mockReturnValue(
|
|
116
120
|
new Blob([new ArrayBuffer(8)]) as any,
|
|
@@ -144,8 +148,8 @@ describe("push", () => {
|
|
|
144
148
|
);
|
|
145
149
|
|
|
146
150
|
expect(archiveMock.pipe).toHaveBeenCalled();
|
|
147
|
-
expect(archiveMock.file).toHaveBeenCalledWith("
|
|
148
|
-
name: "
|
|
151
|
+
expect(archiveMock.file).toHaveBeenCalledWith("src/global.css", {
|
|
152
|
+
name: "global.css",
|
|
149
153
|
});
|
|
150
154
|
expect(archiveMock.directory).toHaveBeenCalledWith("buildDir", false);
|
|
151
155
|
expect(archiveMock.finalize).toHaveBeenCalled();
|
|
@@ -205,4 +209,405 @@ describe("push", () => {
|
|
|
205
209
|
|
|
206
210
|
expect(startMock.succeed).toHaveBeenCalledWith("Published using API key");
|
|
207
211
|
});
|
|
212
|
+
|
|
213
|
+
describe("push configuration", () => {
|
|
214
|
+
it("should fail if both pushModels and pushComponents are disabled", async () => {
|
|
215
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
216
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
217
|
+
...config,
|
|
218
|
+
pushModels: false,
|
|
219
|
+
pushComponents: false,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await push();
|
|
223
|
+
|
|
224
|
+
expect(startMock.fail).toHaveBeenCalledWith(
|
|
225
|
+
"Cannot push: both pushModels and pushComponents are disabled",
|
|
226
|
+
);
|
|
227
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("should only include model files when pushComponents is false", async () => {
|
|
231
|
+
const mockArchiver = {
|
|
232
|
+
finalize: vi.fn(),
|
|
233
|
+
pipe: vi.fn(),
|
|
234
|
+
directory: vi.fn(),
|
|
235
|
+
file: vi.fn(),
|
|
236
|
+
};
|
|
237
|
+
vi.mocked(archiver.create).mockReturnValue(mockArchiver as any);
|
|
238
|
+
|
|
239
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
240
|
+
...config,
|
|
241
|
+
pushModels: true,
|
|
242
|
+
pushComponents: false,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
await push();
|
|
246
|
+
|
|
247
|
+
// Should not include component build directory
|
|
248
|
+
expect(mockArchiver.directory).not.toHaveBeenCalled();
|
|
249
|
+
// Should include model files
|
|
250
|
+
expect(mockArchiver.file).toHaveBeenCalled();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("should only include component files when pushModels is false", async () => {
|
|
254
|
+
const mockArchiver = {
|
|
255
|
+
finalize: vi.fn(),
|
|
256
|
+
pipe: vi.fn(),
|
|
257
|
+
directory: vi.fn(),
|
|
258
|
+
file: vi.fn(),
|
|
259
|
+
};
|
|
260
|
+
vi.mocked(archiver.create).mockReturnValue(mockArchiver as any);
|
|
261
|
+
|
|
262
|
+
vi.mocked(provideConfig).mockResolvedValue({
|
|
263
|
+
...config,
|
|
264
|
+
pushModels: false,
|
|
265
|
+
pushComponents: true,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
await push();
|
|
269
|
+
|
|
270
|
+
// Should include component build directory
|
|
271
|
+
expect(mockArchiver.directory).toHaveBeenCalled();
|
|
272
|
+
// Should not include model files (except global.css which is part of components)
|
|
273
|
+
expect(mockArchiver.file).toHaveBeenCalledTimes(1);
|
|
274
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(expect.anything(), {
|
|
275
|
+
name: "global.css",
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
describe("API key validation", () => {
|
|
281
|
+
it("should fail if API key is not provided", async () => {
|
|
282
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
283
|
+
Object.defineProperties(process, {
|
|
284
|
+
argv: {
|
|
285
|
+
value: ["--api-key"],
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
vi.mocked(getArgumentByKey).mockReturnValue(undefined);
|
|
289
|
+
|
|
290
|
+
await push();
|
|
291
|
+
|
|
292
|
+
expect(startMock.fail).toHaveBeenCalledWith("No API key provided");
|
|
293
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it("should fail if email is not provided with API key", async () => {
|
|
297
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
298
|
+
Object.defineProperties(process, {
|
|
299
|
+
argv: {
|
|
300
|
+
value: ["--api-key", "some-key"],
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
vi.mocked(getArgumentByKey)
|
|
304
|
+
.mockReturnValueOnce("some-key") // API key
|
|
305
|
+
.mockReturnValueOnce(undefined); // Email
|
|
306
|
+
|
|
307
|
+
await push();
|
|
308
|
+
|
|
309
|
+
expect(startMock.fail).toHaveBeenCalledWith(
|
|
310
|
+
"Invalid email provided. Please provide a valid email using --email (-e) flag",
|
|
311
|
+
);
|
|
312
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("should fail if email is invalid", async () => {
|
|
316
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
317
|
+
Object.defineProperties(process, {
|
|
318
|
+
argv: {
|
|
319
|
+
value: ["--api-key", "some-key", "--email", "invalid-email"],
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
vi.mocked(getArgumentByKey)
|
|
323
|
+
.mockReturnValueOnce("some-key") // API key
|
|
324
|
+
.mockReturnValueOnce("invalid-email"); // Invalid email
|
|
325
|
+
|
|
326
|
+
await push();
|
|
327
|
+
|
|
328
|
+
expect(startMock.fail).toHaveBeenCalledWith(
|
|
329
|
+
"Invalid email provided. Please provide a valid email using --email (-e) flag",
|
|
330
|
+
);
|
|
331
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("should accept optional message parameter", async () => {
|
|
335
|
+
Object.defineProperties(process, {
|
|
336
|
+
argv: {
|
|
337
|
+
value: [
|
|
338
|
+
"--api-key",
|
|
339
|
+
"some-key",
|
|
340
|
+
"--email",
|
|
341
|
+
"valid@email.com",
|
|
342
|
+
"--message",
|
|
343
|
+
"test message",
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
vi.mocked(getArgumentByKey)
|
|
348
|
+
.mockReturnValueOnce("some-key") // API key
|
|
349
|
+
.mockReturnValueOnce("valid@email.com") // Email
|
|
350
|
+
.mockReturnValueOnce("test message"); // Message
|
|
351
|
+
|
|
352
|
+
await push();
|
|
353
|
+
|
|
354
|
+
expect(startMock.succeed).toHaveBeenCalledWith("Published using API key");
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
describe("error handling", () => {
|
|
359
|
+
beforeEach(() => {
|
|
360
|
+
// Reset all mocks to their default state
|
|
361
|
+
vi.mocked(getArgumentByKey).mockReturnValue(undefined);
|
|
362
|
+
Object.defineProperties(process, {
|
|
363
|
+
argv: {
|
|
364
|
+
value: [],
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("should fail if build directory does not exist", async () => {
|
|
370
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
371
|
+
vi.mocked(fs.access).mockRejectedValue(new Error("No such directory"));
|
|
372
|
+
vi.mocked(provideConfig).mockResolvedValue(config);
|
|
373
|
+
|
|
374
|
+
await push();
|
|
375
|
+
|
|
376
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
377
|
+
"No embeddable build was produced.",
|
|
378
|
+
);
|
|
379
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it("should fail if token is not available", async () => {
|
|
383
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
384
|
+
vi.mocked(fs.access).mockResolvedValue(undefined);
|
|
385
|
+
vi.mocked(fs.readFile).mockResolvedValue(Buffer.from("{}"));
|
|
386
|
+
vi.mocked(provideConfig).mockResolvedValue(config);
|
|
387
|
+
|
|
388
|
+
await push();
|
|
389
|
+
|
|
390
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
391
|
+
"Expired token. Please login again.",
|
|
392
|
+
);
|
|
393
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it("should handle and report errors during push", async () => {
|
|
397
|
+
const testError = new Error("Test error");
|
|
398
|
+
vi.mocked(provideConfig).mockRejectedValue(testError);
|
|
399
|
+
vi.mocked(fs.access).mockResolvedValue(undefined);
|
|
400
|
+
vi.mocked(fs.readFile).mockImplementation(async () =>
|
|
401
|
+
Buffer.from(`{"access_token":"mocked-token"}`),
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
await push();
|
|
405
|
+
|
|
406
|
+
expect(reportErrorToRollbar).toHaveBeenCalledWith(testError);
|
|
407
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
describe("buildArchive", () => {
|
|
412
|
+
type MockArchiver = {
|
|
413
|
+
finalize: ReturnType<typeof vi.fn>;
|
|
414
|
+
pipe: ReturnType<typeof vi.fn>;
|
|
415
|
+
directory: ReturnType<typeof vi.fn>;
|
|
416
|
+
file: ReturnType<typeof vi.fn>;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
let mockArchiver: MockArchiver;
|
|
420
|
+
let mockOra: {
|
|
421
|
+
start: ReturnType<typeof vi.fn>;
|
|
422
|
+
succeed: ReturnType<typeof vi.fn>;
|
|
423
|
+
fail: ReturnType<typeof vi.fn>;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
beforeEach(() => {
|
|
427
|
+
mockArchiver = {
|
|
428
|
+
finalize: vi.fn(),
|
|
429
|
+
pipe: vi.fn(),
|
|
430
|
+
directory: vi.fn(),
|
|
431
|
+
file: vi.fn(),
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
vi.mocked(archiver.create).mockReturnValue(mockArchiver as any);
|
|
435
|
+
vi.mocked(findFiles).mockResolvedValue([]);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it("should include all file types when both flags are true", async () => {
|
|
439
|
+
vi.mocked(findFiles)
|
|
440
|
+
.mockResolvedValueOnce([
|
|
441
|
+
["model1.cube.yml", "/path/to/model1.cube.yml"],
|
|
442
|
+
["model2.cube.yaml", "/path/to/model2.cube.yaml"],
|
|
443
|
+
])
|
|
444
|
+
.mockResolvedValueOnce([
|
|
445
|
+
["context1.sc.yml", "/path/to/context1.sc.yml"],
|
|
446
|
+
["context2.cc.yml", "/path/to/context2.cc.yml"],
|
|
447
|
+
]);
|
|
448
|
+
|
|
449
|
+
const testConfig = {
|
|
450
|
+
...config,
|
|
451
|
+
pushModels: true,
|
|
452
|
+
pushComponents: true,
|
|
453
|
+
client: {
|
|
454
|
+
...config.client,
|
|
455
|
+
srcDir: "/src",
|
|
456
|
+
},
|
|
457
|
+
} as ResolvedEmbeddableConfig;
|
|
458
|
+
|
|
459
|
+
await buildArchive(testConfig);
|
|
460
|
+
|
|
461
|
+
// Should include component build directory
|
|
462
|
+
expect(mockArchiver.directory).toHaveBeenCalledWith(
|
|
463
|
+
testConfig.client.buildDir,
|
|
464
|
+
false,
|
|
465
|
+
);
|
|
466
|
+
// Should include global.css
|
|
467
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
468
|
+
testConfig.client.globalCss,
|
|
469
|
+
{
|
|
470
|
+
name: "global.css",
|
|
471
|
+
},
|
|
472
|
+
);
|
|
473
|
+
// Should include all model files
|
|
474
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
475
|
+
"/path/to/model1.cube.yml",
|
|
476
|
+
{
|
|
477
|
+
name: "model1.cube.yml",
|
|
478
|
+
},
|
|
479
|
+
);
|
|
480
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
481
|
+
"/path/to/model2.cube.yaml",
|
|
482
|
+
{
|
|
483
|
+
name: "model2.cube.yaml",
|
|
484
|
+
},
|
|
485
|
+
);
|
|
486
|
+
// Should include all preset files
|
|
487
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
488
|
+
"/path/to/context1.sc.yml",
|
|
489
|
+
{
|
|
490
|
+
name: "context1.sc.yml",
|
|
491
|
+
},
|
|
492
|
+
);
|
|
493
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
494
|
+
"/path/to/context2.cc.yml",
|
|
495
|
+
{
|
|
496
|
+
name: "context2.cc.yml",
|
|
497
|
+
},
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it("should only include model files when pushComponents is false", async () => {
|
|
502
|
+
vi.mocked(findFiles)
|
|
503
|
+
.mockResolvedValueOnce([["model.cube.yml", "/path/to/model.cube.yml"]])
|
|
504
|
+
.mockResolvedValueOnce([["context.sc.yml", "/path/to/context.sc.yml"]]);
|
|
505
|
+
|
|
506
|
+
const testConfig = {
|
|
507
|
+
...config,
|
|
508
|
+
pushModels: true,
|
|
509
|
+
pushComponents: false,
|
|
510
|
+
client: {
|
|
511
|
+
...config.client,
|
|
512
|
+
srcDir: "/src",
|
|
513
|
+
},
|
|
514
|
+
} as ResolvedEmbeddableConfig;
|
|
515
|
+
|
|
516
|
+
await buildArchive(testConfig);
|
|
517
|
+
|
|
518
|
+
// Should not include component build directory
|
|
519
|
+
expect(mockArchiver.directory).not.toHaveBeenCalled();
|
|
520
|
+
// Should not include global.css
|
|
521
|
+
expect(mockArchiver.file).not.toHaveBeenCalledWith(
|
|
522
|
+
expect.anything(),
|
|
523
|
+
expect.objectContaining({ name: "global.css" }),
|
|
524
|
+
);
|
|
525
|
+
// Should include model files
|
|
526
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
527
|
+
"/path/to/model.cube.yml",
|
|
528
|
+
{
|
|
529
|
+
name: "model.cube.yml",
|
|
530
|
+
},
|
|
531
|
+
);
|
|
532
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
533
|
+
"/path/to/context.sc.yml",
|
|
534
|
+
{
|
|
535
|
+
name: "context.sc.yml",
|
|
536
|
+
},
|
|
537
|
+
);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it("should only include component files when pushModels is false", async () => {
|
|
541
|
+
const testConfig = {
|
|
542
|
+
...config,
|
|
543
|
+
pushModels: false,
|
|
544
|
+
pushComponents: true,
|
|
545
|
+
client: {
|
|
546
|
+
...config.client,
|
|
547
|
+
srcDir: "/src",
|
|
548
|
+
},
|
|
549
|
+
} as ResolvedEmbeddableConfig;
|
|
550
|
+
|
|
551
|
+
await buildArchive(testConfig);
|
|
552
|
+
|
|
553
|
+
// Should include component build directory
|
|
554
|
+
expect(mockArchiver.directory).toHaveBeenCalledWith(
|
|
555
|
+
testConfig.client.buildDir,
|
|
556
|
+
false,
|
|
557
|
+
);
|
|
558
|
+
// Should include global.css
|
|
559
|
+
expect(mockArchiver.file).toHaveBeenCalledWith(
|
|
560
|
+
testConfig.client.globalCss,
|
|
561
|
+
{
|
|
562
|
+
name: "global.css",
|
|
563
|
+
},
|
|
564
|
+
);
|
|
565
|
+
// Should not include any model files
|
|
566
|
+
expect(findFiles).not.toHaveBeenCalled();
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it("should search in custom directories for model files", async () => {
|
|
570
|
+
const testConfig = {
|
|
571
|
+
...config,
|
|
572
|
+
pushModels: true,
|
|
573
|
+
pushComponents: true,
|
|
574
|
+
client: {
|
|
575
|
+
...config.client,
|
|
576
|
+
srcDir: "/src",
|
|
577
|
+
modelsSrc: "/custom/models/path",
|
|
578
|
+
presetsSrc: "/custom/presets/path",
|
|
579
|
+
},
|
|
580
|
+
} as ResolvedEmbeddableConfig;
|
|
581
|
+
|
|
582
|
+
await buildArchive(testConfig);
|
|
583
|
+
|
|
584
|
+
expect(findFiles).toHaveBeenCalledWith(
|
|
585
|
+
"/custom/models/path",
|
|
586
|
+
expect.any(RegExp),
|
|
587
|
+
);
|
|
588
|
+
expect(findFiles).toHaveBeenCalledWith(
|
|
589
|
+
"/custom/presets/path",
|
|
590
|
+
expect.any(RegExp),
|
|
591
|
+
);
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
it("should use srcDir as fallback when modelsSrc/presetsSrc are not defined", async () => {
|
|
595
|
+
const testConfig = {
|
|
596
|
+
...config,
|
|
597
|
+
pushModels: true,
|
|
598
|
+
pushComponents: true,
|
|
599
|
+
client: {
|
|
600
|
+
...config.client,
|
|
601
|
+
srcDir: "/src",
|
|
602
|
+
modelsSrc: undefined,
|
|
603
|
+
presetsSrc: undefined,
|
|
604
|
+
},
|
|
605
|
+
} as ResolvedEmbeddableConfig;
|
|
606
|
+
|
|
607
|
+
await buildArchive(testConfig);
|
|
608
|
+
|
|
609
|
+
expect(findFiles).toHaveBeenCalledWith("/src", expect.any(RegExp));
|
|
610
|
+
expect(findFiles).toHaveBeenCalledWith("/src", expect.any(RegExp));
|
|
611
|
+
});
|
|
612
|
+
});
|
|
208
613
|
});
|
package/src/push.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { findFiles } from "@embeddable.com/sdk-utils";
|
|
|
14
14
|
import { getToken } from "./login";
|
|
15
15
|
import { checkBuildSuccess, checkNodeVersion, getArgumentByKey } from "./utils";
|
|
16
16
|
import { selectWorkspace } from "./workspaceUtils";
|
|
17
|
+
import { ResolvedEmbeddableConfig } from "./defineConfig";
|
|
17
18
|
|
|
18
19
|
// grab cube files
|
|
19
20
|
export const CUBE_FILES = /^(.*)\.cube\.(ya?ml|js)$/;
|
|
@@ -84,7 +85,7 @@ export default async () => {
|
|
|
84
85
|
}
|
|
85
86
|
};
|
|
86
87
|
|
|
87
|
-
async function pushByApiKey(config:
|
|
88
|
+
async function pushByApiKey(config: ResolvedEmbeddableConfig, spinner: any) {
|
|
88
89
|
const apiKey = getArgumentByKey(["--api-key", "-k"]);
|
|
89
90
|
|
|
90
91
|
if (!apiKey) {
|
|
@@ -113,7 +114,7 @@ async function pushByApiKey(config: any, spinner: any) {
|
|
|
113
114
|
});
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
async function verify(ctx:
|
|
117
|
+
async function verify(ctx: ResolvedEmbeddableConfig) {
|
|
117
118
|
try {
|
|
118
119
|
await fs.access(ctx.client.buildDir);
|
|
119
120
|
} catch (_e) {
|
|
@@ -132,33 +133,55 @@ async function verify(ctx: any) {
|
|
|
132
133
|
return token;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
async function buildArchive(config:
|
|
136
|
+
export async function buildArchive(config: ResolvedEmbeddableConfig) {
|
|
136
137
|
const spinnerArchive = ora("Building...").start();
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
if (!config.pushModels && !config.pushComponents) {
|
|
140
|
+
spinnerArchive.fail(
|
|
141
|
+
"Cannot push: both pushModels and pushComponents are disabled",
|
|
142
|
+
);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
142
145
|
|
|
143
|
-
const
|
|
144
|
-
config.client.presetsSrc || config.client.srcDir,
|
|
145
|
-
PRESET_FILES,
|
|
146
|
-
);
|
|
146
|
+
const filesList: [string, string][] = [];
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
if (config.pushModels) {
|
|
149
|
+
const cubeFilesList = await findFiles(
|
|
150
|
+
config.client.modelsSrc || config.client.srcDir,
|
|
151
|
+
CUBE_FILES,
|
|
152
|
+
);
|
|
153
|
+
const contextFilesList = await findFiles(
|
|
154
|
+
config.client.presetsSrc || config.client.srcDir,
|
|
155
|
+
PRESET_FILES,
|
|
156
|
+
);
|
|
157
|
+
filesList.push(
|
|
158
|
+
...cubeFilesList.map((entry): [string, string] => [
|
|
159
|
+
path.basename(entry[1]),
|
|
160
|
+
entry[1],
|
|
161
|
+
]),
|
|
162
|
+
...contextFilesList.map((entry): [string, string] => [
|
|
163
|
+
path.basename(entry[1]),
|
|
164
|
+
entry[1],
|
|
165
|
+
]),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
152
168
|
|
|
153
|
-
await archive(
|
|
169
|
+
await archive({
|
|
170
|
+
ctx: config,
|
|
171
|
+
filesList,
|
|
172
|
+
isDev: false,
|
|
173
|
+
includeComponents: config.pushComponents,
|
|
174
|
+
});
|
|
154
175
|
return spinnerArchive.succeed("Bundling completed");
|
|
155
176
|
}
|
|
156
177
|
|
|
157
|
-
export async function archive(
|
|
158
|
-
ctx:
|
|
159
|
-
|
|
160
|
-
isDev: boolean
|
|
161
|
-
|
|
178
|
+
export async function archive(args: {
|
|
179
|
+
ctx: ResolvedEmbeddableConfig;
|
|
180
|
+
filesList: [string, string][];
|
|
181
|
+
isDev: boolean;
|
|
182
|
+
includeComponents: boolean;
|
|
183
|
+
}) {
|
|
184
|
+
const { ctx, filesList, isDev, includeComponents } = args;
|
|
162
185
|
const output = fsSync.createWriteStream(ctx.client.archiveFile);
|
|
163
186
|
|
|
164
187
|
const archive = archiver.create("zip", {
|
|
@@ -166,14 +189,14 @@ export async function archive(
|
|
|
166
189
|
});
|
|
167
190
|
|
|
168
191
|
archive.pipe(output);
|
|
169
|
-
if (!isDev) {
|
|
192
|
+
if (!isDev && includeComponents) {
|
|
170
193
|
archive.directory(ctx.client.buildDir, false);
|
|
171
194
|
archive.file(ctx.client.globalCss, {
|
|
172
195
|
name: "global.css",
|
|
173
196
|
});
|
|
174
197
|
}
|
|
175
198
|
|
|
176
|
-
for (const fileData of
|
|
199
|
+
for (const fileData of filesList) {
|
|
177
200
|
archive.file(fileData[1], {
|
|
178
201
|
name: fileData[0],
|
|
179
202
|
});
|
|
@@ -187,8 +210,12 @@ export async function archive(
|
|
|
187
210
|
}
|
|
188
211
|
|
|
189
212
|
export async function sendBuildByApiKey(
|
|
190
|
-
ctx:
|
|
191
|
-
{
|
|
213
|
+
ctx: ResolvedEmbeddableConfig,
|
|
214
|
+
{
|
|
215
|
+
apiKey,
|
|
216
|
+
email,
|
|
217
|
+
message,
|
|
218
|
+
}: { apiKey: string; email: string; message?: string },
|
|
192
219
|
) {
|
|
193
220
|
const { FormData, Blob } = await import("formdata-node");
|
|
194
221
|
const { fileFromPath } = await import("formdata-node/file-from-path");
|
|
@@ -218,7 +245,7 @@ export async function sendBuildByApiKey(
|
|
|
218
245
|
}
|
|
219
246
|
|
|
220
247
|
export async function sendBuild(
|
|
221
|
-
ctx:
|
|
248
|
+
ctx: ResolvedEmbeddableConfig,
|
|
222
249
|
{ workspaceId, token }: { workspaceId: string; token: string },
|
|
223
250
|
) {
|
|
224
251
|
const { FormData } = await import("formdata-node");
|