@embeddable.com/sdk-core 3.1.4 → 3.1.6

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
@@ -4567,9 +4567,18 @@ async function dataModelsValidation(filesList) {
4567
4567
  for (const [_, filePath] of filesList) {
4568
4568
  const fileContentRaw = await fs__namespace.readFile(filePath, "utf8");
4569
4569
  const cube = YAML__namespace.parse(fileContentRaw);
4570
- const safeParse = cubeModelSchema.safeParse(cube);
4571
- if (!safeParse.success) {
4572
- errorFormatter(safeParse.error.issues).forEach((error) => {
4570
+ if (!(cube === null || cube === void 0 ? void 0 : cube.cubes) && !(cube === null || cube === void 0 ? void 0 : cube.views)) {
4571
+ return [`${filePath}: At least one cubes or views must be defined`];
4572
+ }
4573
+ const cubeModelSafeParse = cubeModelSchema.safeParse(cube);
4574
+ const viewModelSafeParse = viewModelSchema.safeParse(cube);
4575
+ if (cube.cubes && !cubeModelSafeParse.success) {
4576
+ errorFormatter(cubeModelSafeParse.error.issues).forEach((error) => {
4577
+ errors.push(`${filePath}: ${error}`);
4578
+ });
4579
+ }
4580
+ if (cube.views && !viewModelSafeParse.success) {
4581
+ errorFormatter(viewModelSafeParse.error.issues).forEach((error) => {
4573
4582
  errors.push(`${filePath}: ${error}`);
4574
4583
  });
4575
4584
  }
@@ -4648,6 +4657,18 @@ const cubeModelSchema = z
4648
4657
  message: "At least one measure or dimension must be defined",
4649
4658
  path: ["cubes"],
4650
4659
  });
4660
+ const viewModelSchema = z.object({
4661
+ views: z.object({
4662
+ name: z.string(),
4663
+ cubes: z
4664
+ .object({
4665
+ join_path: z.string(),
4666
+ })
4667
+ .array()
4668
+ })
4669
+ .array()
4670
+ .min(1),
4671
+ });
4651
4672
  const securityContextSchema = z.array(z.object({
4652
4673
  name: z.string(),
4653
4674
  securityContext: z.object({}), // can be any object
@@ -20004,6 +20025,25 @@ const checkNodeVersion = async () => {
20004
20025
  process.exit(1);
20005
20026
  }
20006
20027
  };
20028
+ /**
20029
+ * Get the value of a process argument by key
20030
+ * Example: getArgumentByKey("--email") or getArgumentByKey(["--email", "-e"])
20031
+ * @param key The key to search for in the process arguments
20032
+ * @returns
20033
+ */
20034
+ const getArgumentByKey = (key) => {
20035
+ if (Array.isArray(key)) {
20036
+ for (const k of key) {
20037
+ if (process.argv.includes(k)) {
20038
+ const index = process.argv.indexOf(k);
20039
+ return index !== -1 ? process.argv[index + 1] : undefined;
20040
+ }
20041
+ }
20042
+ return undefined;
20043
+ }
20044
+ const index = process.argv.indexOf(key);
20045
+ return index !== -1 ? process.argv[index + 1] : undefined;
20046
+ };
20007
20047
 
20008
20048
  var build = async () => {
20009
20049
  try {
@@ -20114,29 +20154,58 @@ const inquirerSelect = import('@inquirer/select');
20114
20154
  const YAML_OR_JS_FILES = /^(.*)\.(cube|sc)\.(ya?ml|js)$/;
20115
20155
  let ora$1;
20116
20156
  var push = async () => {
20117
- var _a;
20157
+ var _a, _b;
20118
20158
  let spinnerPushing;
20119
20159
  try {
20120
20160
  checkNodeVersion();
20121
20161
  ora$1 = (await oraP$1).default;
20122
20162
  const config = await provideConfig();
20123
20163
  const token = await verify(config);
20164
+ if (process.argv.includes("--api-key") || process.argv.includes("-k")) {
20165
+ spinnerPushing = ora$1("Using API key...").start();
20166
+ await pushByApiKey(config, spinnerPushing);
20167
+ spinnerPushing.succeed("Published using API key");
20168
+ return;
20169
+ }
20124
20170
  const { workspaceId, name: workspaceName } = await selectWorkspace(config, token);
20125
- const spinnerArchive = ora$1("Building...").start();
20126
- const filesList = await findFiles(config.client.srcDir, YAML_OR_JS_FILES);
20127
- await archive(config, filesList);
20128
- spinnerArchive.succeed("Bundling completed");
20129
- spinnerPushing = ora$1(`Publishing to ${workspaceName} using ${config.pushBaseUrl}...`).start();
20171
+ const workspacePreviewUrl = `${config.previewBaseUrl}/workspace/${workspaceId}`;
20172
+ await buildArchive(config);
20173
+ spinnerPushing = ora$1(`Publishing to ${workspaceName} using ${workspacePreviewUrl}...`).start();
20130
20174
  await sendBuild(config, { workspaceId, token });
20131
- spinnerPushing.succeed(`Published to ${workspaceName} using ${config.pushBaseUrl}`);
20175
+ spinnerPushing.succeed(`Published to ${workspaceName} using ${workspacePreviewUrl}`);
20132
20176
  }
20133
20177
  catch (error) {
20134
20178
  spinnerPushing === null || spinnerPushing === void 0 ? void 0 : spinnerPushing.fail("Publishing failed");
20135
- console.error(((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || (error === null || error === void 0 ? void 0 : error.message) || error);
20179
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.statusText) === "Unauthorized") {
20180
+ console.error("Unauthorized. Please check your credentials.");
20181
+ }
20182
+ else {
20183
+ console.error(((_b = error.response) === null || _b === void 0 ? void 0 : _b.data) || (error === null || error === void 0 ? void 0 : error.message) || error);
20184
+ }
20136
20185
  await reportErrorToRollbar(error);
20137
20186
  process.exit(1);
20138
20187
  }
20139
20188
  };
20189
+ async function pushByApiKey(config, spinner) {
20190
+ const apiKey = getArgumentByKey(["--api-key", "-k"]);
20191
+ if (!apiKey) {
20192
+ spinner.fail("No API key provided");
20193
+ process.exit(1);
20194
+ }
20195
+ const email = getArgumentByKey(["--email", "-e"]);
20196
+ if (!email || !/\S+@\S+\.\S+/.test(email)) {
20197
+ spinner.fail("Invalid email provided. Please provide a valid email using --email (-e) flag");
20198
+ process.exit(1);
20199
+ }
20200
+ // message is optional
20201
+ const message = getArgumentByKey(["--message", "-m"]);
20202
+ await buildArchive(config);
20203
+ return sendBuildByApiKey(config, {
20204
+ apiKey,
20205
+ email,
20206
+ message,
20207
+ });
20208
+ }
20140
20209
  async function selectWorkspace(ctx, token) {
20141
20210
  const workspaceSpinner = ora$1({
20142
20211
  text: `Fetching workspaces using ${ctx.pushBaseUrl}...`,
@@ -20182,6 +20251,12 @@ async function verify(ctx) {
20182
20251
  }
20183
20252
  return token;
20184
20253
  }
20254
+ async function buildArchive(config) {
20255
+ const spinnerArchive = ora$1("Building...").start();
20256
+ const filesList = await findFiles(config.client.srcDir, YAML_OR_JS_FILES);
20257
+ await archive(config, filesList);
20258
+ return spinnerArchive.succeed("Bundling completed");
20259
+ }
20185
20260
  async function archive(ctx, yamlFiles, includeBuild = true) {
20186
20261
  const output = fs__namespace$1.createWriteStream(ctx.client.archiveFile);
20187
20262
  const _archiver = archiver__namespace.create("zip", {
@@ -20202,13 +20277,30 @@ async function archive(ctx, yamlFiles, includeBuild = true) {
20202
20277
  output.on("close", resolve);
20203
20278
  });
20204
20279
  }
20280
+ async function sendBuildByApiKey(ctx, { apiKey, email, message }) {
20281
+ var _a;
20282
+ const { FormData, Blob } = await import('formdata-node');
20283
+ const { fileFromPath } = await Promise.resolve().then(function () { return fileFromPath$1; });
20284
+ const file = await fileFromPath(ctx.client.archiveFile, "embeddable-build.zip");
20285
+ const form = new FormData();
20286
+ form.set("file", file, "embeddable-build.zip");
20287
+ const metadataBlob = new Blob([JSON.stringify({ authorEmail: email, description: message })], { type: "application/json" });
20288
+ form.set("metadata", metadataBlob, "metadata.json");
20289
+ const response = await uploadFile(form, `${ctx.pushBaseUrl}/api/v1/bundle/upload`, apiKey);
20290
+ await fs__namespace.rm(ctx.client.archiveFile);
20291
+ return { bundleId: (_a = response.data) === null || _a === void 0 ? void 0 : _a.bundleId, email, message };
20292
+ }
20205
20293
  async function sendBuild(ctx, { workspaceId, token }) {
20206
20294
  const { FormData } = await import('formdata-node');
20207
20295
  const { fileFromPath } = await Promise.resolve().then(function () { return fileFromPath$1; });
20208
20296
  const file = await fileFromPath(ctx.client.archiveFile, "embeddable-build.zip");
20209
20297
  const form = new FormData();
20210
20298
  form.set("file", file, "embeddable-build.zip");
20211
- await axios.post(`${ctx.pushBaseUrl}/bundle/${workspaceId}/upload`, form, {
20299
+ await uploadFile(form, `${ctx.pushBaseUrl}/bundle/${workspaceId}/upload`, token);
20300
+ await fs__namespace.rm(ctx.client.archiveFile);
20301
+ }
20302
+ async function uploadFile(formData, url, token) {
20303
+ return axios.post(url, formData, {
20212
20304
  headers: {
20213
20305
  "Content-Type": "multipart/form-data",
20214
20306
  Authorization: `Bearer ${token}`,
@@ -20216,7 +20308,6 @@ async function sendBuild(ctx, { workspaceId, token }) {
20216
20308
  maxContentLength: Infinity,
20217
20309
  maxBodyLength: Infinity,
20218
20310
  });
20219
- await fs__namespace.rm(ctx.client.archiveFile);
20220
20311
  }
20221
20312
  async function getWorkspaces(ctx, token, workspaceSpinner) {
20222
20313
  var _a;