@embeddable.com/sdk-core 3.1.3 → 3.1.5

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/push.d.ts CHANGED
@@ -2,6 +2,11 @@ export declare const YAML_OR_JS_FILES: RegExp;
2
2
  declare const _default: () => Promise<void>;
3
3
  export default _default;
4
4
  export declare function archive(ctx: any, yamlFiles: [string, string][], includeBuild?: boolean): Promise<unknown>;
5
+ export declare function sendBuildByApiKey(ctx: any, { apiKey, email, message }: any): Promise<{
6
+ bundleId: any;
7
+ email: any;
8
+ message: any;
9
+ }>;
5
10
  export declare function sendBuild(ctx: any, { workspaceId, token }: {
6
11
  workspaceId: string;
7
12
  token: string;
package/lib/utils.d.ts CHANGED
@@ -1 +1,8 @@
1
1
  export declare const checkNodeVersion: () => Promise<void>;
2
+ /**
3
+ * Get the value of a process argument by key
4
+ * Example: getArgumentByKey("--email") or getArgumentByKey(["--email", "-e"])
5
+ * @param key The key to search for in the process arguments
6
+ * @returns
7
+ */
8
+ export declare const getArgumentByKey: (key: string | string[]) => string | undefined;
@@ -33,6 +33,8 @@ const NON_JS_TS_EXTENSIONS =
33
33
 
34
34
  const currentDir = dirname(fileURLToPath(import.meta.url));
35
35
 
36
+ const isWindows = process.platform === "win32";
37
+
36
38
  export const resolve = async (specifier, context, nextResolve) => {
37
39
  if (NON_JS_TS_EXTENSIONS.test(specifier)) {
38
40
  const mockModulePath = pathToFileURL(
@@ -50,19 +52,37 @@ export const resolve = async (specifier, context, nextResolve) => {
50
52
 
51
53
  // entrypoint
52
54
  if (!context.parentURL) {
55
+ const processCwd = pathToFileURL(process.cwd()).href;
56
+
57
+ const entryPointPath = isWindows
58
+ ? pathToFileURL(specifier.replace(`${processCwd}/file:/`, "")).href
59
+ : specifier;
60
+
53
61
  return {
54
62
  format: isTS ? "ts" : undefined,
55
- url: specifier,
63
+ url: entryPointPath,
56
64
  shortCircuit: true,
57
65
  };
58
66
  }
67
+
68
+ // define if this is a package import
69
+ const isPackageImport =
70
+ !specifier.startsWith(".") &&
71
+ !specifier.startsWith("/") &&
72
+ !/^[A-Z]:/.test(specifier); // windows path
59
73
  // import/require from external library
60
- if (context.parentURL.includes("/node_modules/") && !isTS) {
74
+ if (
75
+ (context.parentURL.includes("/node_modules/") || isPackageImport) &&
76
+ !isTS
77
+ ) {
61
78
  return nextResolve(specifier);
62
79
  }
80
+
81
+ const isFileUrl = specifier.startsWith("file://");
82
+ const isParentFileUrl = context.parentURL.startsWith("file://");
63
83
  const { resolvedModule } = ts.resolveModuleName(
64
- specifier,
65
- fileURLToPath(context.parentURL),
84
+ isFileUrl ? fileURLToPath(specifier) : specifier,
85
+ isParentFileUrl ? fileURLToPath(context.parentURL) : context.parentURL,
66
86
  tsconfig,
67
87
  host,
68
88
  moduleResolutionCache,
@@ -85,7 +105,12 @@ export const resolve = async (specifier, context, nextResolve) => {
85
105
  // - something TS couldn't resolve
86
106
  // - external library
87
107
  // - local project non-TS file
88
- return nextResolve(specifier);
108
+ const specifierPathOrUrl =
109
+ !resolvedModule?.resolvedFileName?.includes("/node_modules/") && isWindows
110
+ ? pathToFileURL(specifier).href
111
+ : specifier;
112
+
113
+ return nextResolve(specifierPathOrUrl);
89
114
  };
90
115
  const tsconfigForSWCNode = {
91
116
  ...tsconfig,
@@ -110,6 +135,9 @@ export const load = async (url, context, nextLoad) => {
110
135
  shortCircuit: true,
111
136
  };
112
137
  } else {
138
+ if (isWindows && !url.startsWith("file://") && url.includes("node_modules")) {
139
+ return nextLoad(pathToFileURL(url).href, context);
140
+ }
113
141
  return nextLoad(url, context);
114
142
  }
115
143
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embeddable.com/sdk-core",
3
- "version": "3.1.3",
3
+ "version": "3.1.5",
4
4
  "description": "Core Embeddable SDK module responsible for web-components bundling and publishing.",
5
5
  "keywords": [
6
6
  "embeddable",
@@ -0,0 +1,12 @@
1
+ const COMMANDS_MAP = require("../lib/index.js");
2
+
3
+ async function main() {
4
+ const command = process.argv[2];
5
+ const runScript = COMMANDS_MAP[command];
6
+
7
+ if (!runScript) process.exit(1);
8
+
9
+ await runScript();
10
+ }
11
+
12
+ main();
package/src/generate.ts CHANGED
@@ -63,12 +63,15 @@ async function runStencil(ctx: any) {
63
63
  const sys = ctx.dev?.sys || createNodeSys({ process });
64
64
  const devMode = !!ctx.dev;
65
65
 
66
+ const isWindows = process.platform === "win32";
67
+
66
68
  const validated = await loadConfig({
67
69
  initTsConfig: true,
68
70
  logger,
69
71
  sys,
70
72
  config: {
71
73
  devMode,
74
+ maxConcurrentWorkers: isWindows ? 0 : 8, // workers break on windows
72
75
  rootDir: ctx.client.buildDir,
73
76
  configPath: path.resolve(ctx.client.buildDir, "stencil.config.ts"),
74
77
  tsconfig: path.resolve(ctx.client.buildDir, "tsconfig.json"),
package/src/login.ts CHANGED
@@ -1,9 +1,7 @@
1
- import * as path from "node:path";
2
- import * as os from "node:os";
3
1
  import * as fs from "node:fs/promises";
4
2
  import axios from "axios";
5
3
  import provideConfig from "./provideConfig";
6
- import { jwtDecode } from "jwt-decode";
4
+
7
5
  // @ts-ignore
8
6
  import reportErrorToRollbar from "./rollbar.mjs";
9
7
  import { CREDENTIALS_DIR, CREDENTIALS_FILE } from "./credentials";
@@ -12,9 +12,12 @@ export default async () => {
12
12
  process.exit(1);
13
13
  }
14
14
 
15
+ const isWindows = process.platform === "win32";
15
16
  const configPath = fs.existsSync(tsConfigFilePath)
16
17
  ? tsConfigFilePath
17
18
  : configFilePath;
18
19
 
19
- return (await import(configPath)).default;
20
+ const pathOrUrl = isWindows ? url.pathToFileURL(configPath).href : configPath;
21
+
22
+ return (await import(pathOrUrl)).default;
20
23
  };
package/src/push.ts CHANGED
@@ -10,7 +10,7 @@ import reportErrorToRollbar from "./rollbar.mjs";
10
10
 
11
11
  import { findFiles } from "@embeddable.com/sdk-utils";
12
12
  import { getToken } from "./login";
13
- import { checkNodeVersion } from "./utils";
13
+ import { checkNodeVersion, getArgumentByKey } from "./utils";
14
14
 
15
15
  // grab .cube.yml|js and .sc.yml|js files
16
16
  export const YAML_OR_JS_FILES = /^(.*)\.(cube|sc)\.(ya?ml|js)$/;
@@ -27,18 +27,21 @@ export default async () => {
27
27
 
28
28
  const token = await verify(config);
29
29
 
30
+ if (process.argv.includes("--api-key") || process.argv.includes("-k")) {
31
+ spinnerPushing = ora("Using API key...").start();
32
+ await pushByApiKey(config, spinnerPushing);
33
+
34
+ spinnerPushing.succeed("Published using API key");
35
+
36
+ return;
37
+ }
38
+
30
39
  const { workspaceId, name: workspaceName } = await selectWorkspace(
31
40
  config,
32
41
  token,
33
42
  );
34
43
 
35
- const spinnerArchive = ora("Building...").start();
36
-
37
- const filesList = await findFiles(config.client.srcDir, YAML_OR_JS_FILES);
38
-
39
- await archive(config, filesList);
40
- spinnerArchive.succeed("Bundling completed");
41
-
44
+ await buildArchive(config);
42
45
  spinnerPushing = ora(
43
46
  `Publishing to ${workspaceName} using ${config.pushBaseUrl}...`,
44
47
  ).start();
@@ -49,12 +52,46 @@ export default async () => {
49
52
  );
50
53
  } catch (error: any) {
51
54
  spinnerPushing?.fail("Publishing failed");
52
- console.error(error.response?.data || error?.message || error);
55
+ if (error.response?.statusText === "Unauthorized") {
56
+ console.error("Unauthorized. Please check your credentials.");
57
+ } else {
58
+ console.error(error.response?.data || error?.message || error);
59
+ }
60
+
53
61
  await reportErrorToRollbar(error);
54
62
  process.exit(1);
55
63
  }
56
64
  };
57
65
 
66
+ async function pushByApiKey(config: any, spinner: any) {
67
+ const apiKey = getArgumentByKey(["--api-key", "-k"]);
68
+
69
+ if (!apiKey) {
70
+ spinner.fail("No API key provided");
71
+ process.exit(1);
72
+ }
73
+
74
+ const email = getArgumentByKey(["--email", "-e"]);
75
+
76
+ if (!email || !/\S+@\S+\.\S+/.test(email)) {
77
+ spinner.fail(
78
+ "Invalid email provided. Please provide a valid email using --email (-e) flag",
79
+ );
80
+ process.exit(1);
81
+ }
82
+
83
+ // message is optional
84
+ const message = getArgumentByKey(["--message", "-m"]);
85
+
86
+ await buildArchive(config);
87
+
88
+ return sendBuildByApiKey(config, {
89
+ apiKey,
90
+ email,
91
+ message,
92
+ });
93
+ }
94
+
58
95
  async function selectWorkspace(ctx: any, token: string) {
59
96
  const workspaceSpinner = ora({
60
97
  text: `Fetching workspaces using ${ctx.pushBaseUrl}...`,
@@ -112,6 +149,15 @@ async function verify(ctx: any) {
112
149
  return token;
113
150
  }
114
151
 
152
+ async function buildArchive(config: any) {
153
+ const spinnerArchive = ora("Building...").start();
154
+
155
+ const filesList = await findFiles(config.client.srcDir, YAML_OR_JS_FILES);
156
+
157
+ await archive(config, filesList);
158
+ return spinnerArchive.succeed("Bundling completed");
159
+ }
160
+
115
161
  export async function archive(
116
162
  ctx: any,
117
163
  yamlFiles: [string, string][],
@@ -143,6 +189,37 @@ export async function archive(
143
189
  });
144
190
  }
145
191
 
192
+ export async function sendBuildByApiKey(
193
+ ctx: any,
194
+ { apiKey, email, message }: any,
195
+ ) {
196
+ const { FormData, Blob } = await import("formdata-node");
197
+ const { fileFromPath } = await import("formdata-node/file-from-path");
198
+
199
+ const file = await fileFromPath(
200
+ ctx.client.archiveFile,
201
+ "embeddable-build.zip",
202
+ );
203
+
204
+ const form = new FormData();
205
+ form.set("file", file, "embeddable-build.zip");
206
+
207
+ const metadataBlob = new Blob(
208
+ [JSON.stringify({ authorEmail: email, description: message })],
209
+ { type: "application/json" },
210
+ );
211
+ form.set("metadata", metadataBlob, "metadata.json");
212
+
213
+ const response = await uploadFile(
214
+ form,
215
+ `${ctx.pushBaseUrl}/api/v1/bundle/upload`,
216
+ apiKey,
217
+ );
218
+ await fs.rm(ctx.client.archiveFile);
219
+
220
+ return { bundleId: response.data?.bundleId, email, message };
221
+ }
222
+
146
223
  export async function sendBuild(
147
224
  ctx: any,
148
225
  { workspaceId, token }: { workspaceId: string; token: string },
@@ -158,7 +235,17 @@ export async function sendBuild(
158
235
  const form = new FormData();
159
236
  form.set("file", file, "embeddable-build.zip");
160
237
 
161
- await axios.post(`${ctx.pushBaseUrl}/bundle/${workspaceId}/upload`, form, {
238
+ await uploadFile(
239
+ form,
240
+ `${ctx.pushBaseUrl}/bundle/${workspaceId}/upload`,
241
+ token,
242
+ );
243
+
244
+ await fs.rm(ctx.client.archiveFile);
245
+ }
246
+
247
+ async function uploadFile(formData: any, url: string, token: string) {
248
+ return axios.post(url, formData, {
162
249
  headers: {
163
250
  "Content-Type": "multipart/form-data",
164
251
  Authorization: `Bearer ${token}`,
@@ -166,8 +253,6 @@ export async function sendBuild(
166
253
  maxContentLength: Infinity,
167
254
  maxBodyLength: Infinity,
168
255
  });
169
-
170
- await fs.rm(ctx.client.archiveFile);
171
256
  }
172
257
 
173
258
  async function getWorkspaces(ctx: any, token: string, workspaceSpinner: any) {
package/src/utils.ts CHANGED
@@ -22,3 +22,25 @@ export const checkNodeVersion = async () => {
22
22
  process.exit(1);
23
23
  }
24
24
  };
25
+
26
+ /**
27
+ * Get the value of a process argument by key
28
+ * Example: getArgumentByKey("--email") or getArgumentByKey(["--email", "-e"])
29
+ * @param key The key to search for in the process arguments
30
+ * @returns
31
+ */
32
+ export const getArgumentByKey = (key: string | string[]) => {
33
+ if (Array.isArray(key)) {
34
+ for (const k of key) {
35
+ if (process.argv.includes(k)) {
36
+ const index = process.argv.indexOf(k);
37
+ return index !== -1 ? process.argv[index + 1] : undefined;
38
+ }
39
+ }
40
+
41
+ return undefined;
42
+ }
43
+
44
+ const index = process.argv.indexOf(key);
45
+ return index !== -1 ? process.argv[index + 1] : undefined;
46
+ };
@@ -1 +0,0 @@
1
- export {};
package/src/entryPoint.ts DELETED
@@ -1,16 +0,0 @@
1
- import path from "path";
2
- import { fileURLToPath } from "url";
3
-
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const COMMANDS_MAP = await import(path.join(__dirname, "../lib/index.js"));
6
-
7
- async function main() {
8
- const command = process.argv[2];
9
- const runScript = COMMANDS_MAP[command];
10
-
11
- if (!runScript) process.exit(1);
12
-
13
- await runScript();
14
- }
15
-
16
- main();