@embeddable.com/sdk-core 3.7.2 → 3.8.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/index.esm.js +8473 -8151
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +8392 -8069
- package/lib/index.js.map +1 -1
- package/loader/custom-esm-loader.mjs +27 -3
- package/package.json +2 -2
- package/src/dev.test.ts +102 -0
- package/src/dev.ts +14 -8
- package/src/generate.test.ts +50 -1
- package/src/generate.ts +36 -6
|
@@ -59,6 +59,8 @@ const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
|
59
59
|
|
|
60
60
|
const isWindows = process.platform === "win32";
|
|
61
61
|
|
|
62
|
+
const moduleCache = new Map();
|
|
63
|
+
|
|
62
64
|
export const resolve = async (specifier, context, nextResolve) => {
|
|
63
65
|
if (NON_JS_TS_EXTENSIONS.test(specifier)) {
|
|
64
66
|
const mockModulePath = pathToFileURL(
|
|
@@ -72,6 +74,10 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
72
74
|
};
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
if (moduleCache.has(specifier)) {
|
|
78
|
+
return moduleCache.get(specifier);
|
|
79
|
+
}
|
|
80
|
+
|
|
75
81
|
const isTS = EXTENSIONS.some((ext) => specifier.endsWith(ext));
|
|
76
82
|
|
|
77
83
|
// Entry point
|
|
@@ -82,11 +88,15 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
82
88
|
? pathToFileURL(specifier.replace(`${processCwd}/file:/`, "")).href
|
|
83
89
|
: specifier;
|
|
84
90
|
|
|
85
|
-
|
|
91
|
+
const resolved = {
|
|
86
92
|
format: isTS ? "ts" : undefined,
|
|
87
93
|
url: entryPointPath,
|
|
88
94
|
shortCircuit: true,
|
|
89
95
|
};
|
|
96
|
+
|
|
97
|
+
moduleCache.set(specifier, resolved);
|
|
98
|
+
|
|
99
|
+
return resolved;
|
|
90
100
|
}
|
|
91
101
|
|
|
92
102
|
// Determine if this is a package import
|
|
@@ -121,13 +131,17 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
121
131
|
!resolvedModule.resolvedFileName.includes("/node_modules/") &&
|
|
122
132
|
EXTENSIONS.includes(resolvedModule.extension)
|
|
123
133
|
) {
|
|
124
|
-
|
|
134
|
+
const resolved = {
|
|
125
135
|
format: "ts",
|
|
126
136
|
url:
|
|
127
137
|
pathToFileURL(resolvedModule.resolvedFileName).href +
|
|
128
138
|
`?update=${Date.now()}`,
|
|
129
139
|
shortCircuit: true,
|
|
130
140
|
};
|
|
141
|
+
|
|
142
|
+
moduleCache.set(specifier, resolved);
|
|
143
|
+
|
|
144
|
+
return resolved;
|
|
131
145
|
}
|
|
132
146
|
|
|
133
147
|
// Fallback for non-TS files or unresolved modules
|
|
@@ -139,7 +153,13 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
139
153
|
return nextResolve(specifierPathOrUrl);
|
|
140
154
|
};
|
|
141
155
|
|
|
156
|
+
const compiledModuleCache = new Map();
|
|
157
|
+
|
|
142
158
|
export const load = async (url, context, nextLoad) => {
|
|
159
|
+
if (compiledModuleCache.has(url)) {
|
|
160
|
+
return compiledModuleCache.get(url);
|
|
161
|
+
}
|
|
162
|
+
|
|
143
163
|
if (context.format === "ts") {
|
|
144
164
|
const { source } = await nextLoad(url, context);
|
|
145
165
|
const code =
|
|
@@ -147,11 +167,15 @@ export const load = async (url, context, nextLoad) => {
|
|
|
147
167
|
|
|
148
168
|
// Compile the code using @swc-node with the customer's tsconfig
|
|
149
169
|
const compiled = await compile(code, fileURLToPath(url), tsconfig, true);
|
|
150
|
-
|
|
170
|
+
const resolved = {
|
|
151
171
|
format: "module",
|
|
152
172
|
source: compiled,
|
|
153
173
|
shortCircuit: true,
|
|
154
174
|
};
|
|
175
|
+
|
|
176
|
+
compiledModuleCache.set(url, resolved);
|
|
177
|
+
|
|
178
|
+
return resolved;
|
|
155
179
|
} else {
|
|
156
180
|
if (
|
|
157
181
|
isWindows &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embeddable.com/sdk-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0-next.0",
|
|
4
4
|
"description": "Core Embeddable SDK module responsible for web-components bundling and publishing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"embeddable",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@embeddable.com/sdk-utils": "*",
|
|
42
42
|
"@inquirer/select": "^1.3.0",
|
|
43
43
|
"@stencil/core": "^4.18.2",
|
|
44
|
-
"@swc-node/register": "^1.9
|
|
44
|
+
"@swc-node/register": "^1.10.9",
|
|
45
45
|
"archiver": "^5.3.1",
|
|
46
46
|
"axios": "^1.7.2",
|
|
47
47
|
"chokidar": "^3.6.0",
|
package/src/dev.test.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from "vitest";
|
|
2
|
+
import * as http from "node:http";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
import provideConfig from "./provideConfig";
|
|
5
|
+
import { getToken } from "./login";
|
|
6
|
+
import * as chokidar from "chokidar";
|
|
7
|
+
import dev from "./dev";
|
|
8
|
+
import { checkNodeVersion } from "./utils";
|
|
9
|
+
import { createManifest } from "./cleanup";
|
|
10
|
+
import prepare from "./prepare";
|
|
11
|
+
import { WebSocketServer } from "ws";
|
|
12
|
+
|
|
13
|
+
// Mock dependencies
|
|
14
|
+
vi.mock("./buildTypes", () => ({ default: vi.fn() }));
|
|
15
|
+
vi.mock("./prepare", () => ({ default: vi.fn(), removeIfExists: vi.fn() }));
|
|
16
|
+
vi.mock("./generate", () => ({ default: vi.fn() }));
|
|
17
|
+
vi.mock("./provideConfig", () => ({ default: vi.fn() }));
|
|
18
|
+
vi.mock("@stencil/core/sys/node", () => ({
|
|
19
|
+
createNodeLogger: vi.fn(),
|
|
20
|
+
createNodeSys: vi.fn(),
|
|
21
|
+
}));
|
|
22
|
+
vi.mock("ws", () => ({ WebSocketServer: vi.fn() }));
|
|
23
|
+
vi.mock("chokidar", () => ({ watch: vi.fn() }));
|
|
24
|
+
vi.mock("./login", () => ({ getToken: vi.fn(), default: vi.fn() }));
|
|
25
|
+
vi.mock("axios", () => ({ default: { get: vi.fn() } }));
|
|
26
|
+
vi.mock("@embeddable.com/sdk-utils", () => ({ findFiles: vi.fn() }));
|
|
27
|
+
vi.mock("./push", () => ({ archive: vi.fn(), sendBuild: vi.fn() }));
|
|
28
|
+
vi.mock("./validate", () => ({ default: vi.fn() }));
|
|
29
|
+
vi.mock("./utils", () => ({ checkNodeVersion: vi.fn() }));
|
|
30
|
+
vi.mock("./cleanup", () => ({ createManifest: vi.fn() }));
|
|
31
|
+
vi.mock("node:http", () => ({
|
|
32
|
+
createServer: vi.fn(() => ({ listen: vi.fn() })),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
const mockConfig = {
|
|
36
|
+
client: {
|
|
37
|
+
rootDir: "/mock/root",
|
|
38
|
+
buildDir: "/mock/root/.embeddable-dev-build",
|
|
39
|
+
componentDir: "/mock/root/.embeddable-dev-build/component",
|
|
40
|
+
stencilBuild: "/mock/root/.embeddable-dev-build/dist/embeddable-wrapper",
|
|
41
|
+
tmpDir: "/mock/root/.embeddable-dev-tmp",
|
|
42
|
+
selfServeCustomizationDir: "/mock/root/self-serve",
|
|
43
|
+
modelsSrc: "/mock/root/models",
|
|
44
|
+
},
|
|
45
|
+
plugins: [],
|
|
46
|
+
previewBaseUrl: "http://preview.example.com",
|
|
47
|
+
pushBaseUrl: "http://push.example.com",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
describe("dev command", () => {
|
|
51
|
+
let listenMock: Mock;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
listenMock = vi.fn();
|
|
54
|
+
vi.mocked(http.createServer).mockImplementation(
|
|
55
|
+
() =>
|
|
56
|
+
({
|
|
57
|
+
listen: listenMock,
|
|
58
|
+
}) as any,
|
|
59
|
+
);
|
|
60
|
+
vi.mocked(WebSocketServer).mockImplementation(() => {
|
|
61
|
+
return {
|
|
62
|
+
clients: [],
|
|
63
|
+
on: vi.fn(),
|
|
64
|
+
} as any;
|
|
65
|
+
});
|
|
66
|
+
vi.mocked(chokidar.watch).mockReturnValue({
|
|
67
|
+
on: vi.fn(),
|
|
68
|
+
} as any);
|
|
69
|
+
// Mock process.on to avoid actually setting up process listeners
|
|
70
|
+
vi.spyOn(process, "on").mockImplementation(() => process);
|
|
71
|
+
|
|
72
|
+
vi.mocked(provideConfig).mockResolvedValue(mockConfig);
|
|
73
|
+
vi.mocked(getToken).mockResolvedValue("mock-token");
|
|
74
|
+
vi.mocked(axios.get).mockResolvedValue({
|
|
75
|
+
data: "mock-workspace",
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
afterEach(() => {
|
|
80
|
+
vi.restoreAllMocks();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should set up the development environment", async () => {
|
|
84
|
+
// Run the dev command
|
|
85
|
+
await dev();
|
|
86
|
+
|
|
87
|
+
// Verify that the necessary functions were called
|
|
88
|
+
expect(checkNodeVersion).toHaveBeenCalled();
|
|
89
|
+
expect(prepare).toHaveBeenCalled();
|
|
90
|
+
expect(http.createServer).toHaveBeenCalled();
|
|
91
|
+
expect(WebSocketServer).toHaveBeenCalled();
|
|
92
|
+
|
|
93
|
+
// Verify that the server was set up to listen on the correct port
|
|
94
|
+
expect(listenMock).toHaveBeenCalledWith(8926, expect.any(Function));
|
|
95
|
+
|
|
96
|
+
// Call the listen callback to simulate the server being set up
|
|
97
|
+
listenMock.mock.calls[0][1]();
|
|
98
|
+
expect(createManifest).toHaveBeenCalled();
|
|
99
|
+
|
|
100
|
+
await expect.poll(() => chokidar.watch).toBeCalledTimes(2);
|
|
101
|
+
});
|
|
102
|
+
});
|
package/src/dev.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
createNodeSys,
|
|
12
12
|
} from "@stencil/core/sys/node";
|
|
13
13
|
import { RollupWatcher } from "rollup";
|
|
14
|
+
import * as http from "node:http";
|
|
14
15
|
import { IncomingMessage, Server, ServerResponse } from "http";
|
|
15
16
|
import { ChildProcess } from "node:child_process";
|
|
16
17
|
import { WebSocketServer, Server as WSServer } from "ws";
|
|
@@ -56,16 +57,24 @@ const addToGitingore = async () => {
|
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
|
|
60
|
+
const chokidarWatchOptions = {
|
|
61
|
+
ignoreInitial: true,
|
|
62
|
+
usePolling: false, // Ensure polling is disabled
|
|
63
|
+
awaitWriteFinish: {
|
|
64
|
+
stabilityThreshold: 200,
|
|
65
|
+
pollInterval: 100,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
59
69
|
export default async () => {
|
|
60
70
|
checkNodeVersion();
|
|
61
71
|
addToGitingore();
|
|
62
72
|
|
|
63
|
-
const http = require("http");
|
|
64
73
|
ora = (await oraP).default;
|
|
65
74
|
|
|
66
75
|
process.on("warning", (e) => console.warn(e.stack));
|
|
67
76
|
|
|
68
|
-
const logger = createNodeLogger(
|
|
77
|
+
const logger = createNodeLogger();
|
|
69
78
|
const sys = createNodeSys({ process });
|
|
70
79
|
|
|
71
80
|
const defaultConfig = await provideConfig();
|
|
@@ -173,6 +182,7 @@ export default async () => {
|
|
|
173
182
|
|
|
174
183
|
await plugin.validate(config);
|
|
175
184
|
const watcher = await plugin.build(config);
|
|
185
|
+
|
|
176
186
|
await configureWatcher(watcher, config);
|
|
177
187
|
watchers.push(watcher);
|
|
178
188
|
}
|
|
@@ -243,9 +253,7 @@ const onBundleBuildEnd = async (ctx: any) => {
|
|
|
243
253
|
const dataModelAndSecurityContextWatcher = (ctx: any): FSWatcher => {
|
|
244
254
|
const fsWatcher = chokidar.watch(
|
|
245
255
|
[path.resolve(ctx.client.modelsSrc, "**/*.{cube,sc}.{yaml,yml,js}")],
|
|
246
|
-
|
|
247
|
-
ignoreInitial: true,
|
|
248
|
-
},
|
|
256
|
+
chokidarWatchOptions,
|
|
249
257
|
);
|
|
250
258
|
fsWatcher.on("all", async () => {
|
|
251
259
|
await sendDataModelsAndSecurityContextsChanges(ctx);
|
|
@@ -260,9 +268,7 @@ const customSelfServeWatcher = (ctx: any): FSWatcher => {
|
|
|
260
268
|
path.resolve(ctx.client.selfServeCustomizationDir, "style.css"),
|
|
261
269
|
path.resolve(ctx.client.selfServeCustomizationDir, "*.svg"),
|
|
262
270
|
],
|
|
263
|
-
|
|
264
|
-
ignoreInitial: true,
|
|
265
|
-
},
|
|
271
|
+
chokidarWatchOptions,
|
|
266
272
|
);
|
|
267
273
|
|
|
268
274
|
fsWatcher.on("all", async () => {
|
package/src/generate.test.ts
CHANGED
|
@@ -79,7 +79,9 @@ describe("generate", () => {
|
|
|
79
79
|
config: {},
|
|
80
80
|
} as any);
|
|
81
81
|
vi.mocked(createCompiler).mockResolvedValue({
|
|
82
|
-
build: vi.fn()
|
|
82
|
+
build: vi.fn().mockResolvedValue({
|
|
83
|
+
hasError: false,
|
|
84
|
+
}),
|
|
83
85
|
destroy: vi.fn(),
|
|
84
86
|
} as any);
|
|
85
87
|
|
|
@@ -112,4 +114,51 @@ describe("generate", () => {
|
|
|
112
114
|
"stencilBuild/embeddable-wrapper.esm-hash.js",
|
|
113
115
|
);
|
|
114
116
|
});
|
|
117
|
+
|
|
118
|
+
it("should generate bundle in dev mode", async () => {
|
|
119
|
+
const ctx = {
|
|
120
|
+
...config,
|
|
121
|
+
dev: {
|
|
122
|
+
logger: vi.fn(),
|
|
123
|
+
sys: vi.fn(),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
vi.mocked(fs.readFile).mockResolvedValue(
|
|
128
|
+
"replace-this-with-component-name",
|
|
129
|
+
);
|
|
130
|
+
await generate(ctx, "sdk-react");
|
|
131
|
+
|
|
132
|
+
expect(createCompiler).toHaveBeenCalled();
|
|
133
|
+
|
|
134
|
+
expect(fs.writeFile).toHaveBeenCalledWith(
|
|
135
|
+
"componentDir/component.tsx",
|
|
136
|
+
expect.stringContaining("embeddable-component"),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(loadConfig).toHaveBeenCalledWith({
|
|
140
|
+
config: {
|
|
141
|
+
configPath: "buildDir/stencil.config.ts",
|
|
142
|
+
devMode: true,
|
|
143
|
+
enableCache: true,
|
|
144
|
+
maxConcurrentWorkers: 8,
|
|
145
|
+
minifyCss: false,
|
|
146
|
+
minifyJs: false,
|
|
147
|
+
namespace: "embeddable-wrapper",
|
|
148
|
+
outputTargets: [
|
|
149
|
+
{
|
|
150
|
+
type: "dist",
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
rootDir: "buildDir",
|
|
154
|
+
sourceMap: false,
|
|
155
|
+
srcDir: "buildDir/component",
|
|
156
|
+
tsconfig: "buildDir/tsconfig.json",
|
|
157
|
+
watchDirs: ["buildDir/buildName"],
|
|
158
|
+
},
|
|
159
|
+
initTsConfig: true,
|
|
160
|
+
logger: expect.any(Function),
|
|
161
|
+
sys: expect.any(Function),
|
|
162
|
+
});
|
|
163
|
+
});
|
|
115
164
|
});
|
package/src/generate.ts
CHANGED
|
@@ -96,8 +96,8 @@ async function addComponentTagName(filePath: string, bundleHash: string) {
|
|
|
96
96
|
]);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
async function runStencil(ctx: any) {
|
|
100
|
-
const logger = ctx.dev?.logger || createNodeLogger(
|
|
99
|
+
async function runStencil(ctx: any): Promise<void> {
|
|
100
|
+
const logger = ctx.dev?.logger || createNodeLogger();
|
|
101
101
|
const sys = ctx.dev?.sys || createNodeSys({ process });
|
|
102
102
|
const devMode = !!ctx.dev;
|
|
103
103
|
|
|
@@ -109,23 +109,56 @@ async function runStencil(ctx: any) {
|
|
|
109
109
|
sys,
|
|
110
110
|
config: {
|
|
111
111
|
devMode,
|
|
112
|
+
enableCache: true,
|
|
112
113
|
maxConcurrentWorkers: isWindows ? 0 : 8, // workers break on windows
|
|
113
114
|
rootDir: ctx.client.buildDir,
|
|
114
115
|
configPath: path.resolve(ctx.client.buildDir, "stencil.config.ts"),
|
|
115
116
|
tsconfig: path.resolve(ctx.client.buildDir, "tsconfig.json"),
|
|
116
117
|
namespace: "embeddable-wrapper",
|
|
117
118
|
srcDir: path.resolve(ctx.client.buildDir, "component"),
|
|
119
|
+
sourceMap: !devMode,
|
|
120
|
+
minifyJs: !devMode,
|
|
121
|
+
minifyCss: !devMode,
|
|
118
122
|
outputTargets: [
|
|
119
123
|
{
|
|
120
124
|
type: "dist",
|
|
121
125
|
},
|
|
122
126
|
],
|
|
127
|
+
watchDirs: [
|
|
128
|
+
path.resolve(
|
|
129
|
+
ctx.client.buildDir,
|
|
130
|
+
ctx["sdk-react"].outputOptions.buildName,
|
|
131
|
+
),
|
|
132
|
+
],
|
|
123
133
|
},
|
|
124
134
|
});
|
|
125
135
|
|
|
126
136
|
const compiler = await createCompiler(validated.config);
|
|
137
|
+
const buildResults = await compiler.build();
|
|
138
|
+
|
|
139
|
+
if (devMode) {
|
|
140
|
+
// Handle process exit to clean up resources
|
|
141
|
+
const cleanUp = async () => {
|
|
142
|
+
await compiler.destroy();
|
|
143
|
+
process.exit(0);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
process.on("SIGINT", cleanUp);
|
|
147
|
+
process.on("SIGTERM", cleanUp);
|
|
148
|
+
} else {
|
|
149
|
+
if (buildResults.hasError) {
|
|
150
|
+
console.error("Stencil build error:", buildResults.diagnostics);
|
|
151
|
+
throw new Error("Stencil build error");
|
|
152
|
+
} else {
|
|
153
|
+
await handleStencilBuildOutput(ctx);
|
|
154
|
+
}
|
|
155
|
+
await compiler.destroy();
|
|
156
|
+
}
|
|
127
157
|
|
|
128
|
-
|
|
158
|
+
process.chdir(ctx.client.rootDir);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function handleStencilBuildOutput(ctx: any) {
|
|
129
162
|
const entryFilePath = path.resolve(
|
|
130
163
|
ctx.client.stencilBuild,
|
|
131
164
|
"embeddable-wrapper.esm.js",
|
|
@@ -149,9 +182,6 @@ async function runStencil(ctx: any) {
|
|
|
149
182
|
entryFilePath,
|
|
150
183
|
path.resolve(ctx.client.stencilBuild, fileName),
|
|
151
184
|
);
|
|
152
|
-
|
|
153
|
-
await compiler.destroy();
|
|
154
|
-
process.chdir(ctx.client.rootDir);
|
|
155
185
|
}
|
|
156
186
|
|
|
157
187
|
async function generateSourceMap(ctx: any, pluginName: string) {
|