@embeddable.com/sdk-core 3.8.0 → 3.9.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 +47 -16
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +49 -17
- package/lib/index.js.map +1 -1
- package/loader/custom-esm-loader.mjs +9 -3
- package/package.json +2 -2
- package/src/dev.test.ts +103 -0
- package/src/dev.ts +14 -8
- package/src/generate.test.ts +49 -1
- package/src/generate.ts +35 -6
|
@@ -82,11 +82,13 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
82
82
|
? pathToFileURL(specifier.replace(`${processCwd}/file:/`, "")).href
|
|
83
83
|
: specifier;
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
const resolved = {
|
|
86
86
|
format: isTS ? "ts" : undefined,
|
|
87
87
|
url: entryPointPath,
|
|
88
88
|
shortCircuit: true,
|
|
89
89
|
};
|
|
90
|
+
|
|
91
|
+
return resolved;
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
// Determine if this is a package import
|
|
@@ -121,13 +123,15 @@ export const resolve = async (specifier, context, nextResolve) => {
|
|
|
121
123
|
!resolvedModule.resolvedFileName.includes("/node_modules/") &&
|
|
122
124
|
EXTENSIONS.includes(resolvedModule.extension)
|
|
123
125
|
) {
|
|
124
|
-
|
|
126
|
+
const resolved = {
|
|
125
127
|
format: "ts",
|
|
126
128
|
url:
|
|
127
129
|
pathToFileURL(resolvedModule.resolvedFileName).href +
|
|
128
130
|
`?update=${Date.now()}`,
|
|
129
131
|
shortCircuit: true,
|
|
130
132
|
};
|
|
133
|
+
|
|
134
|
+
return resolved;
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
// Fallback for non-TS files or unresolved modules
|
|
@@ -147,11 +151,13 @@ export const load = async (url, context, nextLoad) => {
|
|
|
147
151
|
|
|
148
152
|
// Compile the code using @swc-node with the customer's tsconfig
|
|
149
153
|
const compiled = await compile(code, fileURLToPath(url), tsconfig, true);
|
|
150
|
-
|
|
154
|
+
const resolved = {
|
|
151
155
|
format: "module",
|
|
152
156
|
source: compiled,
|
|
153
157
|
shortCircuit: true,
|
|
154
158
|
};
|
|
159
|
+
|
|
160
|
+
return resolved;
|
|
155
161
|
} else {
|
|
156
162
|
if (
|
|
157
163
|
isWindows &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embeddable.com/sdk-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.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/prompts": "^7.0.0",
|
|
43
43
|
"@stencil/core": "^4.22.0",
|
|
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,103 @@
|
|
|
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
|
+
vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
|
|
72
|
+
|
|
73
|
+
vi.mocked(provideConfig).mockResolvedValue(mockConfig);
|
|
74
|
+
vi.mocked(getToken).mockResolvedValue("mock-token");
|
|
75
|
+
vi.mocked(axios.get).mockResolvedValue({
|
|
76
|
+
data: "mock-workspace",
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
afterEach(() => {
|
|
81
|
+
vi.restoreAllMocks();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should set up the development environment", async () => {
|
|
85
|
+
// Run the dev command
|
|
86
|
+
await dev();
|
|
87
|
+
|
|
88
|
+
// Verify that the necessary functions were called
|
|
89
|
+
expect(checkNodeVersion).toHaveBeenCalled();
|
|
90
|
+
expect(prepare).toHaveBeenCalled();
|
|
91
|
+
expect(http.createServer).toHaveBeenCalled();
|
|
92
|
+
expect(WebSocketServer).toHaveBeenCalled();
|
|
93
|
+
|
|
94
|
+
// Verify that the server was set up to listen on the correct port
|
|
95
|
+
expect(listenMock).toHaveBeenCalledWith(8926, expect.any(Function));
|
|
96
|
+
|
|
97
|
+
// Call the listen callback to simulate the server being set up
|
|
98
|
+
listenMock.mock.calls[0][1]();
|
|
99
|
+
expect(createManifest).toHaveBeenCalled();
|
|
100
|
+
|
|
101
|
+
await expect.poll(() => chokidar.watch).toBeCalledTimes(2);
|
|
102
|
+
});
|
|
103
|
+
});
|
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";
|
|
@@ -57,16 +58,24 @@ const addToGitingore = async () => {
|
|
|
57
58
|
}
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
const chokidarWatchOptions = {
|
|
62
|
+
ignoreInitial: true,
|
|
63
|
+
usePolling: false, // Ensure polling is disabled
|
|
64
|
+
awaitWriteFinish: {
|
|
65
|
+
stabilityThreshold: 200,
|
|
66
|
+
pollInterval: 100,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
60
70
|
export default async () => {
|
|
61
71
|
checkNodeVersion();
|
|
62
72
|
addToGitingore();
|
|
63
73
|
|
|
64
|
-
const http = require("http");
|
|
65
74
|
ora = (await oraP).default;
|
|
66
75
|
|
|
67
76
|
process.on("warning", (e) => console.warn(e.stack));
|
|
68
77
|
|
|
69
|
-
const logger = createNodeLogger(
|
|
78
|
+
const logger = createNodeLogger();
|
|
70
79
|
const sys = createNodeSys({ process });
|
|
71
80
|
|
|
72
81
|
const defaultConfig = await provideConfig();
|
|
@@ -176,6 +185,7 @@ export default async () => {
|
|
|
176
185
|
|
|
177
186
|
await plugin.validate(config);
|
|
178
187
|
const watcher = await plugin.build(config);
|
|
188
|
+
|
|
179
189
|
await configureWatcher(watcher, config);
|
|
180
190
|
watchers.push(watcher);
|
|
181
191
|
}
|
|
@@ -246,9 +256,7 @@ const onBundleBuildEnd = async (ctx: any) => {
|
|
|
246
256
|
const dataModelAndSecurityContextWatcher = (ctx: any): FSWatcher => {
|
|
247
257
|
const fsWatcher = chokidar.watch(
|
|
248
258
|
[path.resolve(ctx.client.modelsSrc, "**/*.{cube,sc}.{yaml,yml,js}")],
|
|
249
|
-
|
|
250
|
-
ignoreInitial: true,
|
|
251
|
-
},
|
|
259
|
+
chokidarWatchOptions,
|
|
252
260
|
);
|
|
253
261
|
fsWatcher.on("all", async () => {
|
|
254
262
|
await sendDataModelsAndSecurityContextsChanges(ctx);
|
|
@@ -263,9 +271,7 @@ const customSelfServeWatcher = (ctx: any): FSWatcher => {
|
|
|
263
271
|
path.resolve(ctx.client.selfServeCustomizationDir, "style.css"),
|
|
264
272
|
path.resolve(ctx.client.selfServeCustomizationDir, "*.svg"),
|
|
265
273
|
],
|
|
266
|
-
|
|
267
|
-
ignoreInitial: true,
|
|
268
|
-
},
|
|
274
|
+
chokidarWatchOptions,
|
|
269
275
|
);
|
|
270
276
|
|
|
271
277
|
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,50 @@ 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
|
+
maxConcurrentWorkers: 8,
|
|
144
|
+
minifyCss: false,
|
|
145
|
+
minifyJs: false,
|
|
146
|
+
namespace: "embeddable-wrapper",
|
|
147
|
+
outputTargets: [
|
|
148
|
+
{
|
|
149
|
+
type: "dist",
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
rootDir: "buildDir",
|
|
153
|
+
sourceMap: false,
|
|
154
|
+
srcDir: "buildDir/component",
|
|
155
|
+
tsconfig: "buildDir/tsconfig.json",
|
|
156
|
+
watchDirs: ["buildDir/buildName"],
|
|
157
|
+
},
|
|
158
|
+
initTsConfig: true,
|
|
159
|
+
logger: expect.any(Function),
|
|
160
|
+
sys: expect.any(Function),
|
|
161
|
+
});
|
|
162
|
+
});
|
|
115
163
|
});
|
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
|
|
|
@@ -115,17 +115,49 @@ async function runStencil(ctx: any) {
|
|
|
115
115
|
tsconfig: path.resolve(ctx.client.buildDir, "tsconfig.json"),
|
|
116
116
|
namespace: "embeddable-wrapper",
|
|
117
117
|
srcDir: path.resolve(ctx.client.buildDir, "component"),
|
|
118
|
+
sourceMap: !devMode,
|
|
119
|
+
minifyJs: !devMode,
|
|
120
|
+
minifyCss: !devMode,
|
|
118
121
|
outputTargets: [
|
|
119
122
|
{
|
|
120
123
|
type: "dist",
|
|
121
124
|
},
|
|
122
125
|
],
|
|
126
|
+
watchDirs: [
|
|
127
|
+
path.resolve(
|
|
128
|
+
ctx.client.buildDir,
|
|
129
|
+
ctx["sdk-react"].outputOptions.buildName,
|
|
130
|
+
),
|
|
131
|
+
],
|
|
123
132
|
},
|
|
124
133
|
});
|
|
125
134
|
|
|
126
135
|
const compiler = await createCompiler(validated.config);
|
|
136
|
+
const buildResults = await compiler.build();
|
|
137
|
+
|
|
138
|
+
if (devMode) {
|
|
139
|
+
// Handle process exit to clean up resources
|
|
140
|
+
const cleanUp = async () => {
|
|
141
|
+
await compiler.destroy();
|
|
142
|
+
process.exit(0);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
process.on("SIGINT", cleanUp);
|
|
146
|
+
process.on("SIGTERM", cleanUp);
|
|
147
|
+
} else {
|
|
148
|
+
if (buildResults.hasError) {
|
|
149
|
+
console.error("Stencil build error:", buildResults.diagnostics);
|
|
150
|
+
throw new Error("Stencil build error");
|
|
151
|
+
} else {
|
|
152
|
+
await handleStencilBuildOutput(ctx);
|
|
153
|
+
}
|
|
154
|
+
await compiler.destroy();
|
|
155
|
+
}
|
|
127
156
|
|
|
128
|
-
|
|
157
|
+
process.chdir(ctx.client.rootDir);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function handleStencilBuildOutput(ctx: any) {
|
|
129
161
|
const entryFilePath = path.resolve(
|
|
130
162
|
ctx.client.stencilBuild,
|
|
131
163
|
"embeddable-wrapper.esm.js",
|
|
@@ -149,9 +181,6 @@ async function runStencil(ctx: any) {
|
|
|
149
181
|
entryFilePath,
|
|
150
182
|
path.resolve(ctx.client.stencilBuild, fileName),
|
|
151
183
|
);
|
|
152
|
-
|
|
153
|
-
await compiler.destroy();
|
|
154
|
-
process.chdir(ctx.client.rootDir);
|
|
155
184
|
}
|
|
156
185
|
|
|
157
186
|
async function generateSourceMap(ctx: any, pluginName: string) {
|