Skip to content

Commit 0363dca

Browse files
authored
vs-extension: build/packaging hardening + Phase 1 correctness & UX fixes (#475)
* chore(vs-extension): harden build and packaging pipeline - Move SDK package.json inlining from a post-bundle string-replace to a source-load esbuild plugin so minification cannot break the substitution. Build-time assertion guards against drift if SDK call sites change. - Stage all SDK data dirs (cip-proto, script-api, content-schemas, scaffolds) into dist/data/ — was only scaffolds, leaving latent breakage when content-validation / CIP / Script API code paths reach packageRoot. - Replace zip/unzip CLI shellouts in inject-script-types.mjs with pure-Node JSZip. Removes the host-binary requirement (improves Windows compatibility) and the [Content_Types].xml shell-glob escapes. Fixes a regression where injected entries were emitted without their leading-dot extension form. - Production hardening: minify, drop:['debugger'], target node22, legalComments:'none'. - esbuild define injects __EXT_VERSION__ and __TELEMETRY_CONNECTION_STRING__ so telemetry.ts no longer readFileSync(package.json) at runtime. - Single syncStaticAssets() shared by watch and production paths so the two layouts can no longer drift. - vscode:prepublish now builds @salesforce/b2c-script-types before the SDK and the bundle, so a stale plugin tree can no longer ship. - .vscodeignore: drop dead negations for HTML files that don't exist; add dist/meta.json so ANALYZE_BUNDLE artifacts don't ship. * fix(vs-extension): correctness and UX hardening (Phase 1) Implements 7 audit items targeting present-day defects, not hypothetical threats. Trust model: SCAPI specs are trusted, user-typed input via own forms is trusted, single-developer workstation. - ContentFileSystemProvider.stat() now returns a stable mtime (cached in a Map<string, number> keyed by libraryId:contentId, bumped on writeFile success) instead of Date.now() per call. VS Code no longer thinks content files are constantly mutating; phantom "file modified externally" prompts and silent buffer reloads are gone. - WebDAV FileSystemProvider.rename() now delegates to instance.webdav.move instead of unconditionally throwing NoPermissions. F2-rename works in the explorer; cross-root attempts and 412 conflicts map to the right FileSystemError values. - Replaced sync fs.readFileSync/existsSync/statSync on the activation hot path (B2CExtensionConfig) with vscode.workspace.fs async equivalents. CAP file-decoration provider now answers via the existing capUris Set in O(1) instead of two syscalls per paint. - Long-running operations (sandbox clone polling, CAP install, deploy, content export, Swagger UI proxy fetches) are now cancellable via withProgress({cancellable: true}) and token.isCancellationRequested checks at loop boundaries. Server-side abort requires SDK AbortSignal support which is a separate change. - Every TreeDataProvider now sets a stable TreeItem.id (e.g., realm:NAME, sandbox:REALM:ID, webdav:TYPE:PATH, api:family:NAME, etc.) so expand state survives refresh and treeView.reveal() works without try/catch fallback. - 11 commands that previously bypassed registerSafeCommand — including b2c-dx.sandbox.clone (a billable mutation) — now route through the SafetyGuard pipeline with feature-usage telemetry. Added scriptTypes to FeatureCategory and the command-prefix mapping. - Dead code removal: createDeleteAndDeployCommand, tempDirs cleanup loop in cartridge-commands, openExternal branch in Page Designer message handler, and the never-implemented b2c-dx.codeSync.diffCartridge stub.
1 parent 21bbed0 commit 0363dca

29 files changed

Lines changed: 513 additions & 357 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'b2c-vs-extension': patch
3+
---
4+
5+
Harden the extension build and packaging pipeline. The esbuild bundle now minifies, drops debugger statements, targets Node 22 (matching VS Code 1.105's runtime), and inlines `require('@salesforce/b2c-tooling-sdk/package.json')` at SDK source-load time so minification can no longer break the substitution. SDK data directories that the runtime expects (`cip-proto`, `script-api`, `content-schemas`, `scaffolds`) are all staged into `dist/data/` instead of just `scaffolds`. The `inject-script-types` step that adds the bundled TypeScript Server plugin to the VSIX now uses pure-Node JSZip instead of shelling out to `zip`/`unzip`, removing the host-binary requirement (Windows CI compatibility) and fixing a regression where `[Content_Types].xml` entries for the injected plugin were emitted without their leading dot. The extension version and telemetry connection string are now injected as build-time constants, eliminating a runtime `readFileSync(package.json)`. `vscode:prepublish` now builds `@salesforce/b2c-script-types` before the extension bundle so a stale plugin tree can no longer ship.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'b2c-vs-extension': patch
3+
---
4+
5+
Correctness and UX hardening pass across the extension:
6+
7+
- **Content libraries**: `ContentFileSystemProvider.stat()` now returns a stable `mtime` instead of `Date.now()` per call. VS Code no longer believes content files are constantly mutating, eliminating phantom "file modified externally" prompts and silent buffer reloads that could clobber unsaved edits.
8+
- **WebDAV explorer**: F2-rename now works. The `rename()` method delegates to the SDK's `webdav.move` (already used by drag-and-drop) instead of throwing `NoPermissions`. Cross-root attempts and 412 conflicts are mapped to the right `vscode.FileSystemError`.
9+
- **Activation performance**: replaced sync `fs.readFileSync` / `existsSync` / `statSync` on the activation hot path (`B2CExtensionConfig`) and in the per-paint CAP file-decoration provider with `vscode.workspace.fs` async equivalents and a Set lookup, respectively. CAP decorations now answer in O(1) without filesystem syscalls.
10+
- **Cancellation**: long-running operations (sandbox clone polling, CAP install, deploy, content export, Swagger UI proxy fetches) now show a working Cancel button. Cancelling stops the local poll/wait; aborting the server-side operation requires SDK `AbortSignal` support which is a separate change.
11+
- **Tree state stability**: every tree provider (sandbox, WebDAV, content libraries, API browser, cartridges) now sets a stable `TreeItem.id`, so expand/collapse state survives refresh and `treeView.reveal()` works without try/catch fallback.
12+
- **Safety + telemetry coverage**: 11 contributed commands previously bypassed `registerSafeCommand`, including `b2c-dx.sandbox.clone` (a billable operation). All now route through the safety guard and feature-usage telemetry. Added a `scriptTypes` feature category and command-prefix mapping.
13+
- **Dead code removal**: removed an unused `createDeleteAndDeployCommand`, the unused `tempDirs` cleanup loop in `cartridge-commands`, the dead `openExternal` branch in the Page Designer webview message handler, and the never-implemented `b2c-dx.codeSync.diffCartridge` command.

packages/b2c-vs-extension/.vscodeignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
src/**
44
!src/webview.html
55
!src/api-browser/swagger-webview.html
6-
!src/storefront-next-cartridge.html
7-
!src/scapi-explorer.html
8-
!src/ods-management.html
96
out/**
107
**/node_modules/**
8+
dist/meta.json
119

1210
!src/template/**
1311
.gitignore

packages/b2c-vs-extension/package.json

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,6 @@
569569
"icon": "$(cloud-download)",
570570
"category": "B2C DX - Code Sync"
571571
},
572-
{
573-
"command": "b2c-dx.codeSync.diffCartridge",
574-
"title": "Compare with Instance",
575-
"icon": "$(diff)",
576-
"category": "B2C DX - Code Sync"
577-
},
578572
{
579573
"command": "b2c-dx.codeSync.addToSitePath",
580574
"title": "Add to Site Cartridge Path",
@@ -1022,10 +1016,6 @@
10221016
"command": "b2c-dx.codeSync.downloadCartridge",
10231017
"when": "false"
10241018
},
1025-
{
1026-
"command": "b2c-dx.codeSync.diffCartridge",
1027-
"when": "false"
1028-
},
10291019
{
10301020
"command": "b2c-dx.codeSync.addToSitePath",
10311021
"when": "false"
@@ -1040,7 +1030,7 @@
10401030
"scripts": {
10411031
"build": "node scripts/esbuild-bundle.mjs",
10421032
"watch": "node scripts/esbuild-bundle.mjs --watch",
1043-
"vscode:prepublish": "pnpm run typecheck:agent && pnpm --filter @salesforce/b2c-tooling-sdk run build && node scripts/esbuild-bundle.mjs",
1033+
"vscode:prepublish": "pnpm run typecheck:agent && pnpm --filter @salesforce/b2c-script-types run build && pnpm --filter @salesforce/b2c-tooling-sdk run build && node scripts/esbuild-bundle.mjs",
10441034
"package": "pnpm exec vsce package --no-dependencies && node scripts/inject-script-types.mjs",
10451035
"lint": "eslint",
10461036
"lint:agent": "eslint --quiet",
@@ -1062,6 +1052,7 @@
10621052
"@vscode/vsce": "^3.9.1",
10631053
"c8": "catalog:",
10641054
"esbuild": "^0.24.0",
1055+
"jszip": "3.10.1",
10651056
"swagger-ui-dist": "^5.18.0",
10661057
"eslint": "catalog:",
10671058
"eslint-config-prettier": "catalog:",

packages/b2c-vs-extension/scripts/esbuild-bundle.mjs

Lines changed: 139 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,121 +4,195 @@
44
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
55
*/
66
/**
7-
* Bundles the extension with esbuild. Injects a shim for import.meta.url so
8-
* SDK code that uses createRequire(import.meta.url) works in CJS output.
7+
* Bundles the extension with esbuild.
8+
*
9+
* - Shims `import.meta.url` so SDK code that uses `createRequire(import.meta.url)`
10+
* works in CJS output.
11+
* - Inlines `require('@salesforce/b2c-tooling-sdk/package.json')` and
12+
* `require.resolve(...)` calls at LOAD time (i.e., on the SDK source before
13+
* esbuild parses/minifies it) so the runtime doesn't try to resolve out of
14+
* node_modules — `vsce --no-dependencies` never ships node_modules. Doing
15+
* this at load time (rather than as a post-bundle string-replace) means
16+
* minification can't break the pattern. A build-time assertion guards against
17+
* regex drift.
18+
* - Stages static assets (SDK data dirs, script-types plugin, swagger-ui)
19+
* into dist/ via a single helper used by both watch and production paths.
20+
* - Build-time `define` injects the extension version and telemetry connection
21+
* string so the runtime doesn't have to readFileSync(package.json).
922
*/
1023
import esbuild from 'esbuild';
1124
import fs from 'node:fs';
12-
import path from 'path';
13-
import {fileURLToPath} from 'url';
25+
import path from 'node:path';
26+
import {fileURLToPath} from 'node:url';
1427

1528
const __filename = fileURLToPath(import.meta.url);
1629
const __dirname = path.dirname(__filename);
1730

1831
// scripts/ -> package root
1932
const pkgRoot = path.resolve(__dirname, '..');
33+
const sdkRoot = path.join(pkgRoot, '..', 'b2c-tooling-sdk');
34+
const sdkPkgJsonPath = path.join(sdkRoot, 'package.json');
35+
const scriptTypesRoot = path.join(pkgRoot, '..', 'b2c-script-types');
36+
const watchMode = process.argv.includes('--watch');
37+
38+
const extPkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8'));
2039

2140
// In CJS there is no import.meta; SDK's version.js uses createRequire(import.meta.url). Shim it.
2241
// Use globalThis so the value is visible inside all module wrappers in the bundle.
2342
const IMPORT_META_URL_SHIM =
2443
"if (typeof globalThis.__import_meta_url === 'undefined') { try { globalThis.__import_meta_url = require('url').pathToFileURL(__filename).href; } catch (_) {} }";
2544

45+
// Match a `require()` of the SDK package.json *before* minification. Bound to the literal
46+
// `require` identifier (not a renamed minified local) because we run on source files.
47+
const SDK_PKG_REQUIRE_RE = /require\s*\(\s*["']@salesforce\/b2c-tooling-sdk\/package\.json["']\s*\)/g;
48+
const SDK_PKG_REQUIRE_RESOLVE_RE =
49+
/require\s*\.\s*resolve\s*\(\s*["']@salesforce\/b2c-tooling-sdk\/package\.json["']\s*\)/g;
50+
// `require('path').join(__dirname, 'package.json')` evaluates at runtime to <extension-dist>/package.json,
51+
// so `path.dirname(...)` gives the extension's dist/ directory — where SDK data dirs are staged.
52+
const SDK_PKG_REQUIRE_RESOLVE_REPLACEMENT = "require('path').join(__dirname, 'package.json')";
53+
54+
let sdkPkgRequireHits = 0;
55+
let sdkPkgResolveHits = 0;
56+
let sdkPkgInlinedJson;
57+
2658
function loaderFor(filePath) {
59+
if (filePath.endsWith('.tsx')) return 'tsx';
2760
const ext = path.extname(filePath);
28-
if (ext === '.ts' || filePath.endsWith('.tsx')) return 'ts';
61+
if (ext === '.ts') return 'ts';
2962
return 'js';
3063
}
3164

32-
const importMetaUrlPlugin = {
33-
name: 'import-meta-url-shim',
65+
/**
66+
* Source-level transform plugin:
67+
* - Replace `import.meta.url` with a globalThis shim (CJS has no import.meta).
68+
* - Inline `require('@salesforce/b2c-tooling-sdk/package.json')` and `require.resolve(...)`
69+
* with the JSON literal / runtime __dirname path. Done at LOAD time so minification can't
70+
* break the pattern.
71+
*/
72+
const sdkSourceShimPlugin = {
73+
name: 'sdk-source-shim',
3474
setup(build) {
75+
build.onStart(() => {
76+
sdkPkgRequireHits = 0;
77+
sdkPkgResolveHits = 0;
78+
sdkPkgInlinedJson = JSON.stringify(JSON.parse(fs.readFileSync(sdkPkgJsonPath, 'utf8')));
79+
});
3580
build.onLoad({filter: /\.(ts|tsx|js|mjs|cjs)$/}, (args) => {
36-
const contents = fs.readFileSync(args.path, 'utf-8');
37-
const replaced = contents.includes('import.meta.url')
38-
? contents.replace(/import\.meta\.url/g, 'globalThis.__import_meta_url')
39-
: contents;
40-
return {contents: replaced, loader: loaderFor(args.path)};
81+
const original = fs.readFileSync(args.path, 'utf8');
82+
const hasImportMeta = original.includes('import.meta.url');
83+
const hasRequirePkg = SDK_PKG_REQUIRE_RE.test(original);
84+
// test() advances lastIndex; reset before re-using elsewhere.
85+
SDK_PKG_REQUIRE_RE.lastIndex = 0;
86+
const hasResolvePkg = SDK_PKG_REQUIRE_RESOLVE_RE.test(original);
87+
SDK_PKG_REQUIRE_RESOLVE_RE.lastIndex = 0;
88+
89+
if (!hasImportMeta && !hasRequirePkg && !hasResolvePkg) return null;
90+
91+
let contents = original;
92+
if (hasImportMeta) {
93+
contents = contents.replace(/import\.meta\.url/g, 'globalThis.__import_meta_url');
94+
}
95+
if (hasResolvePkg) {
96+
// Must run BEFORE the bare-require replacement, since `require.resolve(...)` also matches the bare regex.
97+
contents = contents.replace(SDK_PKG_REQUIRE_RESOLVE_RE, () => {
98+
sdkPkgResolveHits++;
99+
return SDK_PKG_REQUIRE_RESOLVE_REPLACEMENT;
100+
});
101+
}
102+
if (hasRequirePkg) {
103+
contents = contents.replace(SDK_PKG_REQUIRE_RE, () => {
104+
sdkPkgRequireHits++;
105+
return sdkPkgInlinedJson;
106+
});
107+
}
108+
return {contents, loader: loaderFor(args.path)};
109+
});
110+
build.onEnd((result) => {
111+
if (watchMode) return;
112+
if (result.errors && result.errors.length > 0) return;
113+
if (sdkPkgRequireHits === 0 && sdkPkgResolveHits === 0) {
114+
throw new Error(
115+
'[sdk-source-shim] expected at least one require()/require.resolve() of ' +
116+
"'@salesforce/b2c-tooling-sdk/package.json' in SDK source, found none. " +
117+
'SDK code may have changed; update SDK_PKG_REQUIRE_RE / SDK_PKG_REQUIRE_RESOLVE_RE.',
118+
);
119+
}
120+
console.log(
121+
`[sdk-source-shim] inlined ${sdkPkgRequireHits} require() and ${sdkPkgResolveHits} require.resolve() call(s).`,
122+
);
41123
});
42124
},
43125
};
44126

45-
// Inline SDK package.json so the bundle doesn't require() it at runtime (vsce --no-dependencies
46-
// never includes node_modules). The SDK uses createRequire() so esbuild leaves it as runtime require;
47-
// we replace that require in the bundle output with the actual JSON (post-build).
48-
// Also replace require.resolve('@salesforce/b2c-tooling-sdk/package.json') so it doesn't throw when
49-
// the extension runs from a VSIX (no node_modules). We use __dirname so path.dirname(...) is the extension dist.
50-
const sdkPkgJsonPath = path.join(pkgRoot, '..', 'b2c-tooling-sdk', 'package.json');
51-
const REQUIRE_RESOLVE_PACKAGE_JSON_RE =
52-
/require\d*\.resolve\s*\(\s*["']@salesforce\/b2c-tooling-sdk\/package\.json["']\s*\)/g;
53-
const REQUIRE_RESOLVE_REPLACEMENT = "require('path').join(__dirname, 'package.json')";
54-
55-
// Copy SDK scaffold templates into dist/ so the extension can find them at runtime.
56-
// The extension passes this path explicitly via createScaffoldRegistry({ builtInScaffoldsDir }).
57-
const sdkRoot = path.join(pkgRoot, '..', 'b2c-tooling-sdk');
58-
59-
function copySdkScaffolds() {
60-
const src = path.join(sdkRoot, 'data', 'scaffolds');
61-
const dest = path.join(pkgRoot, 'dist', 'data', 'scaffolds');
62-
if (!fs.existsSync(src)) return;
127+
function copyDir(src, dest) {
128+
if (!fs.existsSync(src)) return false;
63129
fs.cpSync(src, dest, {recursive: true});
130+
return true;
64131
}
65132

66-
// Stage @salesforce/b2c-script-types into the extension's node_modules so the
67-
// TypeScript Server plugin (declared in contributes.typescriptServerPlugins) is
68-
// resolvable from the extension root at runtime, even with `vsce --no-dependencies`.
133+
/**
134+
* Copy SDK data directories into dist/data/. The SDK uses
135+
* `path.dirname(require.resolve('@salesforce/b2c-tooling-sdk/package.json'))` as packageRoot
136+
* and joins data subdirs to it. Since `sdkSourceShimPlugin` rewrites that resolve to
137+
* `path.join(__dirname, 'package.json')`, packageRoot becomes the extension's dist/, so
138+
* these data dirs must be staged there.
139+
*/
140+
const SDK_DATA_DIRS = ['scaffolds', 'cip-proto', 'script-api', 'content-schemas'];
141+
function copySdkDataDirs() {
142+
for (const dir of SDK_DATA_DIRS) {
143+
copyDir(path.join(sdkRoot, 'data', dir), path.join(pkgRoot, 'dist', 'data', dir));
144+
}
145+
}
146+
147+
/** Stage @salesforce/b2c-script-types into the extension's node_modules so the TypeScript Server
148+
* plugin (declared in contributes.typescriptServerPlugins) is resolvable from the extension root
149+
* at runtime, even with `vsce --no-dependencies`. */
69150
function copyScriptTypesPlugin() {
70-
const src = path.join(pkgRoot, '..', 'b2c-script-types');
71-
const dest = path.join(pkgRoot, 'node_modules', '@salesforce', 'b2c-script-types');
72-
if (!fs.existsSync(src)) {
73-
console.warn('[script-types] source not found, skipping:', src);
151+
if (!fs.existsSync(scriptTypesRoot)) {
152+
console.warn('[script-types] source not found, skipping:', scriptTypesRoot);
74153
return;
75154
}
155+
const dest = path.join(pkgRoot, 'node_modules', '@salesforce', 'b2c-script-types');
76156
// Wipe any stale staged copy (or pnpm symlink) so we don't accumulate.
77157
if (fs.existsSync(dest) || fs.lstatSync(dest, {throwIfNoEntry: false})) {
78158
fs.rmSync(dest, {recursive: true, force: true});
79159
}
80160
fs.mkdirSync(path.dirname(dest), {recursive: true});
81-
// Copy only the runtime artifacts; skip src/, eslint/tsconfig dev files.
82161
for (const entry of ['package.json', 'plugin', 'types', 'README.md', 'jsconfig.template.json']) {
83-
const s = path.join(src, entry);
162+
const s = path.join(scriptTypesRoot, entry);
84163
if (!fs.existsSync(s)) continue;
85164
fs.cpSync(s, path.join(dest, entry), {recursive: true});
86165
}
87166
console.log('[script-types] staged', path.relative(pkgRoot, dest));
88167
}
89168

90-
function inlineSdkPackageJson() {
91-
const outPath = path.join(pkgRoot, 'dist', 'extension.cjs');
92-
let str = fs.readFileSync(outPath, 'utf8');
93-
const sdkPkg = JSON.stringify(JSON.parse(fs.readFileSync(sdkPkgJsonPath, 'utf8')));
94-
str = str.replace(/require\d*\s*\(\s*["']@salesforce\/b2c-tooling-sdk\/package\.json["']\s*\)/g, sdkPkg);
95-
str = str.replace(REQUIRE_RESOLVE_PACKAGE_JSON_RE, REQUIRE_RESOLVE_REPLACEMENT);
96-
fs.writeFileSync(outPath, str, 'utf8');
97-
}
98-
99169
/** Copy Swagger UI assets to dist/swagger-ui/ for the API Browser webview. */
100170
function copySwaggerUiAssets() {
101-
// Resolve the swagger-ui-dist package location (pnpm may hoist it)
102171
const swaggerUiIndex = fileURLToPath(import.meta.resolve('swagger-ui-dist'));
103172
const swaggerUiDist = path.dirname(swaggerUiIndex);
104173
const outDir = path.join(pkgRoot, 'dist', 'swagger-ui');
105174
fs.mkdirSync(outDir, {recursive: true});
106-
107175
const files = ['swagger-ui-bundle.js', 'swagger-ui-standalone-preset.js', 'swagger-ui.css'];
108176
for (const file of files) {
109177
fs.copyFileSync(path.join(swaggerUiDist, file), path.join(outDir, file));
110178
}
111-
console.log(`[swagger-ui] Copied ${files.length} assets to dist/swagger-ui/`);
179+
console.log(`[swagger-ui] copied ${files.length} assets to dist/swagger-ui/`);
112180
}
113181

114-
const watchMode = process.argv.includes('--watch');
182+
/** Single helper invoked by both watch and production paths so they ship the same dist/ layout. */
183+
function syncStaticAssets() {
184+
copySdkDataDirs();
185+
copyScriptTypesPlugin();
186+
copySwaggerUiAssets();
187+
}
115188

116189
const buildOptions = {
117190
entryPoints: [path.join(pkgRoot, 'src', 'extension.ts')],
118191
bundle: true,
119192
platform: 'node',
120193
format: 'cjs',
121-
target: 'node18',
194+
// VS Code 1.105 ships Node 22; align with engines.
195+
target: 'node22',
122196
outfile: path.join(pkgRoot, 'dist', 'extension.cjs'),
123197
sourcemap: true,
124198
metafile: true,
@@ -128,27 +202,31 @@ const buildOptions = {
128202
conditions: watchMode ? ['development', 'require', 'node', 'default'] : ['require', 'node', 'default'],
129203
mainFields: ['main', 'module'],
130204
banner: {js: IMPORT_META_URL_SHIM},
131-
plugins: [importMetaUrlPlugin],
205+
plugins: [sdkSourceShimPlugin],
206+
// Build-time constants — read once at bundle time so the runtime doesn't readFileSync(package.json).
207+
define: {
208+
__EXT_VERSION__: JSON.stringify(extPkg.version),
209+
__TELEMETRY_CONNECTION_STRING__: JSON.stringify(extPkg.telemetry?.connectionString ?? ''),
210+
},
211+
minify: !watchMode,
212+
drop: watchMode ? [] : ['debugger'],
213+
legalComments: 'none',
132214
logLevel: 'info',
133215
};
134216

135217
if (watchMode) {
136-
copySdkScaffolds();
137-
copyScriptTypesPlugin();
218+
syncStaticAssets();
138219
const ctx = await esbuild.context(buildOptions);
139220
await ctx.watch();
140221
console.log('[esbuild] watching for changes...');
141222
} else {
142223
const result = await esbuild.build(buildOptions);
143224

144-
inlineSdkPackageJson();
145-
copySdkScaffolds();
146-
copyScriptTypesPlugin();
147-
copySwaggerUiAssets();
225+
syncStaticAssets();
148226

149227
if (result.metafile && process.env.ANALYZE_BUNDLE) {
150228
const metaPath = path.join(pkgRoot, 'dist', 'meta.json');
151-
fs.writeFileSync(metaPath, JSON.stringify(result.metafile, null, 2), 'utf-8');
229+
fs.writeFileSync(metaPath, JSON.stringify(result.metafile, null, 2), 'utf8');
152230
const inputs = Object.entries(result.metafile.inputs).map(([file, info]) => ({
153231
file: path.relative(pkgRoot, file),
154232
bytes: info.bytes,

0 commit comments

Comments
 (0)