@embeddable.com/sdk-core 3.9.2 → 3.9.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/index.js CHANGED
@@ -680,14 +680,7 @@ const getPackageVersion = (packageName) => {
680
680
  return undefined;
681
681
  }
682
682
  };
683
-
684
- var cleanup = async (ctx) => {
685
- await extractBuild(ctx);
686
- await removeObsoleteDir(ctx.client.buildDir);
687
- await moveBuildTOBuildDir(ctx);
688
- };
689
- async function createManifest({ ctx, typesFileName, metaFileName, editorsMetaFileName, stencilWrapperFileName, }) {
690
- var _a, _b, _c, _d;
683
+ const getSDKVersions = () => {
691
684
  const packageNames = [
692
685
  "@embeddable.com/core",
693
686
  "@embeddable.com/react",
@@ -702,6 +695,30 @@ async function createManifest({ ctx, typesFileName, metaFileName, editorsMetaFil
702
695
  }
703
696
  return acc;
704
697
  }, {});
698
+ return sdkVersions;
699
+ };
700
+ const hrtimeToISO8601 = (hrtime) => {
701
+ if (hrtime === null || hrtime === undefined) {
702
+ return "";
703
+ }
704
+ const seconds = hrtime[0];
705
+ const nanoseconds = hrtime[1];
706
+ // Convert time components
707
+ const totalSeconds = seconds + nanoseconds / 1e9;
708
+ const minutes = Math.floor(totalSeconds / 60);
709
+ const remainingSeconds = totalSeconds % 60;
710
+ // Format ISO 8601 duration without hours
711
+ return `PT${minutes > 0 ? minutes + "M" : ""}${remainingSeconds.toFixed(3)}S`;
712
+ };
713
+
714
+ var cleanup = async (ctx) => {
715
+ await extractBuild(ctx);
716
+ await removeObsoleteDir(ctx.client.buildDir);
717
+ await moveBuildTOBuildDir(ctx);
718
+ };
719
+ async function createManifest({ ctx, typesFileName, metaFileName, editorsMetaFileName, stencilWrapperFileName, }) {
720
+ var _a, _b, _c, _d;
721
+ const sdkVersions = getSDKVersions();
705
722
  // identify user's package manager and its version
706
723
  let packageManager = "npm";
707
724
  if ((_a = process.env.npm_config_user_agent) === null || _a === void 0 ? void 0 : _a.includes("yarn")) {
@@ -727,6 +744,9 @@ async function createManifest({ ctx, typesFileName, metaFileName, editorsMetaFil
727
744
  sdkVersions,
728
745
  packageManager,
729
746
  packageManagerVersion,
747
+ metrics: {
748
+ buildTime: hrtimeToISO8601(ctx.buildTime),
749
+ },
730
750
  },
731
751
  };
732
752
  await fs__namespace.writeFile(path__namespace.join(ctx.client.tmpDir, "embeddable-manifest.json"), JSON.stringify(manifest));
@@ -21226,9 +21246,96 @@ async function getUserData() {
21226
21246
  }
21227
21247
  }
21228
21248
 
21249
+ const LOG_DIR = path__namespace.join(process.cwd(), ".embeddable", "logs");
21250
+ const ERROR_LOG_FILE = path__namespace.join(LOG_DIR, "error.log");
21251
+ const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5 MB
21252
+ const MAX_LOG_FILES = 5;
21253
+ async function initLogger(command) {
21254
+ try {
21255
+ await fs__namespace.mkdir(LOG_DIR, { recursive: true });
21256
+ }
21257
+ catch (error) {
21258
+ console.error("Failed to create log directory:", error);
21259
+ }
21260
+ setupGlobalErrorHandlers(command);
21261
+ }
21262
+ async function logError({ command, breadcrumbs, error, }) {
21263
+ const sdkVersions = getSDKVersions();
21264
+ const logEntry = {
21265
+ timestamp: new Date().toISOString(),
21266
+ command,
21267
+ breadcrumbs,
21268
+ error: error instanceof Error
21269
+ ? `${error.name}: ${error.message}\n${error.stack}`
21270
+ : String(error),
21271
+ };
21272
+ const logMessage = `
21273
+ [${logEntry.timestamp}] Command: ${logEntry.command}
21274
+ Breadcrumbs: ${logEntry.breadcrumbs.join(" > ")}
21275
+ Error: ${logEntry.error}
21276
+ OS: ${process.platform}
21277
+ Node: ${process.version}
21278
+ SDK Versions: ${JSON.stringify(sdkVersions, null, 2)}
21279
+ ----------------------------------------
21280
+ `;
21281
+ try {
21282
+ await rotateLogIfNeeded();
21283
+ await fs__namespace.appendFile(ERROR_LOG_FILE, logMessage);
21284
+ console.error(`An error occurred during ${command}. Check the log file for details: ${ERROR_LOG_FILE}`);
21285
+ }
21286
+ catch (error) {
21287
+ console.error("Failed to write to log file:", error);
21288
+ }
21289
+ }
21290
+ async function rotateLogIfNeeded() {
21291
+ try {
21292
+ const stats = await fs__namespace.stat(ERROR_LOG_FILE);
21293
+ if (stats.size < MAX_LOG_SIZE) {
21294
+ return;
21295
+ }
21296
+ for (let i = MAX_LOG_FILES - 1; i > 0; i--) {
21297
+ const oldFile = `${ERROR_LOG_FILE}.${i}`;
21298
+ const newFile = `${ERROR_LOG_FILE}.${i + 1}`;
21299
+ try {
21300
+ await fs__namespace.rename(oldFile, newFile);
21301
+ }
21302
+ catch (error) {
21303
+ // Ignore error if file doesn't exist
21304
+ }
21305
+ }
21306
+ await fs__namespace.rename(ERROR_LOG_FILE, `${ERROR_LOG_FILE}.1`);
21307
+ await fs__namespace.writeFile(ERROR_LOG_FILE, ""); // Create a new empty log file
21308
+ }
21309
+ catch (error) {
21310
+ if (error.code !== "ENOENT") {
21311
+ console.error("Error rotating log file:", error);
21312
+ }
21313
+ }
21314
+ }
21315
+ function setupGlobalErrorHandlers(command) {
21316
+ process.on("uncaughtException", async (error) => {
21317
+ await logError({ command, breadcrumbs: ["uncaughtException"], error });
21318
+ console.error("An uncaught error occurred. Check the log file for details.");
21319
+ process.exit(1);
21320
+ });
21321
+ process.on("unhandledRejection", async (reason) => {
21322
+ await logError({
21323
+ command,
21324
+ breadcrumbs: ["unhandledRejection"],
21325
+ error: reason,
21326
+ });
21327
+ console.error("An unhandled rejection occurred. Check the log file for details.");
21328
+ process.exit(1);
21329
+ });
21330
+ }
21331
+
21229
21332
  var build = async () => {
21333
+ await initLogger("build");
21334
+ const breadcrumbs = [];
21230
21335
  try {
21336
+ const startTime = process.hrtime();
21231
21337
  checkNodeVersion();
21338
+ breadcrumbs.push("checkNodeVersion");
21232
21339
  removeBuildSuccessFlag();
21233
21340
  const config = await provideConfig();
21234
21341
  await validate(config);
@@ -21236,16 +21343,24 @@ var build = async () => {
21236
21343
  await buildTypes(config);
21237
21344
  for (const getPlugin of config.plugins) {
21238
21345
  const plugin = getPlugin();
21346
+ breadcrumbs.push(`${plugin.pluginName}: validate`);
21239
21347
  await plugin.validate(config);
21348
+ breadcrumbs.push(`${plugin.pluginName}: build`);
21240
21349
  await plugin.build(config);
21350
+ breadcrumbs.push(`${plugin.pluginName}: cleanup`);
21241
21351
  await plugin.cleanup(config);
21242
21352
  }
21243
21353
  // NOTE: likely this will be called inside the loop above if we decide to support clients with mixed frameworks simultaneously.
21354
+ breadcrumbs.push("generate");
21244
21355
  await generate(config, "sdk-react");
21356
+ // Calculating build time in seconds
21357
+ config.buildTime = process.hrtime(startTime);
21358
+ breadcrumbs.push("cleanup");
21245
21359
  await cleanup(config);
21246
21360
  await storeBuildSuccessFlag();
21247
21361
  }
21248
21362
  catch (error) {
21363
+ await logError({ command: "build", breadcrumbs, error });
21249
21364
  await reportErrorToRollbar(error);
21250
21365
  console.log(error);
21251
21366
  process.exit(1);
@@ -21256,12 +21371,16 @@ const oraP$2 = import('ora');
21256
21371
  const openP = import('open');
21257
21372
  var login = async () => {
21258
21373
  var _a;
21374
+ await initLogger("login");
21375
+ const breadcrumbs = [];
21259
21376
  const ora = (await oraP$2).default;
21260
21377
  const authenticationSpinner = ora("Waiting for code verification...").start();
21261
21378
  try {
21262
21379
  const open = (await openP).default;
21263
21380
  const config = await provideConfig();
21381
+ breadcrumbs.push("provideConfig");
21264
21382
  await resolveFiles();
21383
+ breadcrumbs.push("resolveFiles");
21265
21384
  const deviceCodePayload = {
21266
21385
  client_id: config.authClientId,
21267
21386
  audience: config.audienceUrl,
@@ -21297,6 +21416,7 @@ var login = async () => {
21297
21416
  }
21298
21417
  catch (error) {
21299
21418
  authenticationSpinner.fail("Authentication failed. Please try again.");
21419
+ await logError({ command: "login", breadcrumbs, error });
21300
21420
  await reportErrorToRollbar(error);
21301
21421
  console.log(error);
21302
21422
  process.exit(1);
@@ -21385,10 +21505,12 @@ const oraP$1 = import('ora');
21385
21505
  const YAML_OR_JS_FILES = /^(.*)\.(cube|sc)\.(ya?ml|js)$/;
21386
21506
  let ora$1;
21387
21507
  var push = async () => {
21388
- var _a, _b;
21508
+ await initLogger("push");
21509
+ const breadcrumbs = [];
21389
21510
  let spinnerPushing;
21390
21511
  try {
21391
21512
  checkNodeVersion();
21513
+ breadcrumbs.push("checkNodeVersion");
21392
21514
  const isBuildSuccess = await checkBuildSuccess();
21393
21515
  if (!isBuildSuccess) {
21394
21516
  console.error("Build failed or not completed. Please run `embeddable:build` first.");
@@ -21398,29 +21520,29 @@ var push = async () => {
21398
21520
  const config = await provideConfig();
21399
21521
  if (process.argv.includes("--api-key") || process.argv.includes("-k")) {
21400
21522
  spinnerPushing = ora$1("Using API key...").start();
21523
+ breadcrumbs.push("push by api key");
21401
21524
  await pushByApiKey(config, spinnerPushing);
21402
21525
  spinnerPushing.succeed("Published using API key");
21403
21526
  return;
21404
21527
  }
21528
+ breadcrumbs.push("push by standard login");
21405
21529
  const token = await verify(config);
21406
21530
  spinnerPushing = ora$1()
21407
21531
  .start()
21408
21532
  .info("No API Key provided. Standard login will be used.");
21533
+ breadcrumbs.push("select workspace");
21409
21534
  const { workspaceId, name: workspaceName } = await selectWorkspace(ora$1, config, token);
21410
21535
  const workspacePreviewUrl = `${config.previewBaseUrl}/workspace/${workspaceId}`;
21536
+ breadcrumbs.push("build archive");
21411
21537
  await buildArchive(config);
21412
21538
  spinnerPushing.info(`Publishing to ${workspaceName} using ${workspacePreviewUrl}...`);
21539
+ breadcrumbs.push("send build");
21413
21540
  await sendBuild(config, { workspaceId, token });
21414
21541
  spinnerPushing.succeed(`Published to ${workspaceName} using ${workspacePreviewUrl}`);
21415
21542
  }
21416
21543
  catch (error) {
21417
21544
  spinnerPushing === null || spinnerPushing === void 0 ? void 0 : spinnerPushing.fail("Publishing failed");
21418
- if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.statusText) === "Unauthorized") {
21419
- console.error("Unauthorized. Please check your credentials.");
21420
- }
21421
- else {
21422
- console.error(((_b = error.response) === null || _b === void 0 ? void 0 : _b.data) || (error === null || error === void 0 ? void 0 : error.message) || error);
21423
- }
21545
+ await logError({ command: "push", breadcrumbs, error });
21424
21546
  await reportErrorToRollbar(error);
21425
21547
  process.exit(1);
21426
21548
  }
@@ -21559,96 +21681,111 @@ const chokidarWatchOptions = {
21559
21681
  };
21560
21682
  var dev = async () => {
21561
21683
  var _a, _b;
21562
- checkNodeVersion();
21563
- addToGitingore();
21564
- ora = (await oraP).default;
21565
- process.on("warning", (e) => console.warn(e.stack));
21566
- const logger = node.createNodeLogger();
21567
- const sys = node.createNodeSys({ process });
21568
- const defaultConfig = await provideConfig();
21569
- const buildDir = path__namespace$1.resolve(defaultConfig.client.rootDir, BUILD_DEV_DIR);
21570
- const config = {
21571
- ...defaultConfig,
21572
- dev: {
21573
- watch: true,
21574
- logger,
21575
- sys,
21576
- },
21577
- client: {
21578
- ...defaultConfig.client,
21579
- buildDir,
21580
- componentDir: path__namespace$1.resolve(buildDir, "component"),
21581
- stencilBuild: path__namespace$1.resolve(buildDir, "dist", "embeddable-wrapper"),
21582
- tmpDir: path__namespace$1.resolve(defaultConfig.client.rootDir, ".embeddable-dev-tmp"),
21583
- },
21584
- };
21585
- await prepare(config);
21586
- const finalhandler = require("finalhandler");
21587
- const serveStatic = require("serve-static");
21588
- const serve = serveStatic(config.client.buildDir);
21589
- const workspacePreparation = ora("Preparing workspace...").start();
21684
+ await initLogger("dev");
21685
+ const breadcrumbs = [];
21590
21686
  try {
21591
- previewWorkspace = await getPreviewWorkspace(workspacePreparation, config);
21592
- }
21593
- catch (e) {
21594
- workspacePreparation.fail(((_b = (_a = e.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errorMessage) || "Unknown error: " + e.message);
21595
- process.exit(1);
21596
- }
21597
- workspacePreparation.succeed("Workspace is ready");
21598
- const server = http__namespace.createServer((request, res) => {
21599
- var _a;
21600
- res.setHeader("Access-Control-Allow-Origin", "*");
21601
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
21602
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
21603
- if (request.method === "OPTIONS") {
21604
- // Respond to OPTIONS requests with just the CORS headers and a 200 status code
21605
- res.writeHead(200);
21606
- res.end();
21607
- return;
21608
- }
21609
- const done = finalhandler(request, res);
21687
+ breadcrumbs.push("run dev");
21688
+ checkNodeVersion();
21689
+ addToGitingore();
21690
+ ora = (await oraP).default;
21691
+ process.on("warning", (e) => console.warn(e.stack));
21692
+ const logger = node.createNodeLogger();
21693
+ const sys = node.createNodeSys({ process });
21694
+ const defaultConfig = await provideConfig();
21695
+ const buildDir = path__namespace$1.resolve(defaultConfig.client.rootDir, BUILD_DEV_DIR);
21696
+ const config = {
21697
+ ...defaultConfig,
21698
+ dev: {
21699
+ watch: true,
21700
+ logger,
21701
+ sys,
21702
+ },
21703
+ client: {
21704
+ ...defaultConfig.client,
21705
+ buildDir,
21706
+ componentDir: path__namespace$1.resolve(buildDir, "component"),
21707
+ stencilBuild: path__namespace$1.resolve(buildDir, "dist", "embeddable-wrapper"),
21708
+ tmpDir: path__namespace$1.resolve(defaultConfig.client.rootDir, ".embeddable-dev-tmp"),
21709
+ },
21710
+ };
21711
+ breadcrumbs.push("prepare config");
21712
+ await prepare(config);
21713
+ const finalhandler = require("finalhandler");
21714
+ const serveStatic = require("serve-static");
21715
+ const serve = serveStatic(config.client.buildDir);
21716
+ const workspacePreparation = ora("Preparing workspace...").start();
21717
+ breadcrumbs.push("get preview workspace");
21610
21718
  try {
21611
- if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.endsWith(GLOBAL_CSS)) {
21612
- res.writeHead(200, { "Content-Type": "text/css" });
21613
- res.end(require$$2__namespace.readFileSync(config.client.globalCss));
21614
- return;
21615
- }
21719
+ previewWorkspace = await getPreviewWorkspace(workspacePreparation, config);
21616
21720
  }
21617
- catch (_b) { }
21618
- serve(request, res, done);
21619
- });
21620
- wss = new ws.WebSocketServer({ server });
21621
- server.listen(SERVER_PORT, async () => {
21622
- const watchers = [];
21623
- if (sys === null || sys === void 0 ? void 0 : sys.onProcessInterrupt) {
21624
- sys.onProcessInterrupt(async () => await onClose(server, sys, watchers, config));
21721
+ catch (e) {
21722
+ workspacePreparation.fail(((_b = (_a = e.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errorMessage) || "Unknown error: " + e.message);
21723
+ process.exit(1);
21625
21724
  }
21626
- await createManifest({
21627
- ctx: {
21628
- ...config,
21629
- client: {
21630
- ...config.client,
21631
- tmpDir: buildDir,
21725
+ workspacePreparation.succeed("Workspace is ready");
21726
+ const server = http__namespace.createServer((request, res) => {
21727
+ var _a;
21728
+ res.setHeader("Access-Control-Allow-Origin", "*");
21729
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
21730
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
21731
+ if (request.method === "OPTIONS") {
21732
+ // Respond to OPTIONS requests with just the CORS headers and a 200 status code
21733
+ res.writeHead(200);
21734
+ res.end();
21735
+ return;
21736
+ }
21737
+ const done = finalhandler(request, res);
21738
+ try {
21739
+ if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.endsWith(GLOBAL_CSS)) {
21740
+ res.writeHead(200, { "Content-Type": "text/css" });
21741
+ res.end(require$$2__namespace.readFileSync(config.client.globalCss));
21742
+ return;
21743
+ }
21744
+ }
21745
+ catch (_b) { }
21746
+ serve(request, res, done);
21747
+ });
21748
+ wss = new ws.WebSocketServer({ server });
21749
+ server.listen(SERVER_PORT, async () => {
21750
+ const watchers = [];
21751
+ if (sys === null || sys === void 0 ? void 0 : sys.onProcessInterrupt) {
21752
+ sys.onProcessInterrupt(async () => await onClose(server, sys, watchers, config));
21753
+ }
21754
+ breadcrumbs.push("create manifest");
21755
+ await createManifest({
21756
+ ctx: {
21757
+ ...config,
21758
+ client: {
21759
+ ...config.client,
21760
+ tmpDir: buildDir,
21761
+ },
21632
21762
  },
21633
- },
21634
- typesFileName: "embeddable-types.js",
21635
- stencilWrapperFileName: "embeddable-wrapper.js",
21636
- metaFileName: "embeddable-components-meta.js",
21637
- editorsMetaFileName: "embeddable-editors-meta.js",
21763
+ typesFileName: "embeddable-types.js",
21764
+ stencilWrapperFileName: "embeddable-wrapper.js",
21765
+ metaFileName: "embeddable-components-meta.js",
21766
+ editorsMetaFileName: "embeddable-editors-meta.js",
21767
+ });
21768
+ await sendDataModelsAndSecurityContextsChanges(config);
21769
+ for (const getPlugin of config.plugins) {
21770
+ const plugin = getPlugin();
21771
+ breadcrumbs.push("validate plugin");
21772
+ await plugin.validate(config);
21773
+ breadcrumbs.push("build plugin");
21774
+ const watcher = await plugin.build(config);
21775
+ breadcrumbs.push("configure watcher");
21776
+ await configureWatcher(watcher, config);
21777
+ watchers.push(watcher);
21778
+ }
21779
+ const dataModelAndSecurityContextWatch = dataModelAndSecurityContextWatcher(config);
21780
+ const customGlobalCssWatch = globalCssWatcher(config);
21781
+ watchers.push(dataModelAndSecurityContextWatch);
21782
+ watchers.push(customGlobalCssWatch);
21638
21783
  });
21639
- await sendDataModelsAndSecurityContextsChanges(config);
21640
- for (const getPlugin of config.plugins) {
21641
- const plugin = getPlugin();
21642
- await plugin.validate(config);
21643
- const watcher = await plugin.build(config);
21644
- await configureWatcher(watcher, config);
21645
- watchers.push(watcher);
21646
- }
21647
- const dataModelAndSecurityContextWatch = dataModelAndSecurityContextWatcher(config);
21648
- const customGlobalCssWatch = globalCssWatcher(config);
21649
- watchers.push(dataModelAndSecurityContextWatch);
21650
- watchers.push(customGlobalCssWatch);
21651
- });
21784
+ }
21785
+ catch (error) {
21786
+ await logError({ command: "dev", breadcrumbs, error });
21787
+ process.exit(1);
21788
+ }
21652
21789
  };
21653
21790
  const configureWatcher = async (watcher, ctx) => {
21654
21791
  watcher.on("change", (path) => {
@@ -21832,7 +21969,7 @@ var defineConfig = ({ plugins, pushBaseUrl, audienceUrl, authDomain, authClientI
21832
21969
  };
21833
21970
 
21834
21971
  var name = "@embeddable.com/sdk-core";
21835
- var version = "3.9.2";
21972
+ var version = "3.9.4";
21836
21973
  var description = "Core Embeddable SDK module responsible for web-components bundling and publishing.";
21837
21974
  var keywords = [
21838
21975
  "embeddable",