extension-develop 4.0.22 → 4.0.24

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.
@@ -7,7 +7,7 @@ import { RspackDevServer } from "@rspack/dev-server";
7
7
  import { merge } from "webpack-merge";
8
8
  import { WebSocket, WebSocketServer } from "ws";
9
9
  import { classifyReloadFromSources, attachLifecycleStream, readContentScriptCount, humanLine, buildSourceFeatureIndex, createChangedSourcesTracker, createLifecycleStream, dispatchReload } from "./839.mjs";
10
- import { autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, asAbsolute, isGeckoBasedBrowser, createPlaywrightMetadataWriter, autoExitModeEnabled, getSessionRunId, loadCustomConfig, loadBrowserConfig, getDistPath, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./101.mjs";
10
+ import { autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, asAbsolute, shouldWarnPortConflict, isGeckoBasedBrowser, createPlaywrightMetadataWriter, autoExitModeEnabled, getSessionRunId, loadCustomConfig, loadBrowserConfig, getDistPath, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./101.mjs";
11
11
  import { CONTROL_WS_PATH, writePersistedControlPort, writeControlToken, clearControlToken, readPersistedControlPort } from "./887.mjs";
12
12
  import { hasProjectDependency, findNearestProjectManifestDirSync } from "./80.mjs";
13
13
  import { setupNoBrowserBannerOnFirstDone, webpackConfig, resolveConnectableHost, setupCompilerLifecycleHooks } from "./0~rspack-config.mjs";
@@ -863,10 +863,12 @@ class PortManager {
863
863
  const isValidRequested = 'number' == typeof requestedPort && requestedPort >= 0 && requestedPort < 65536;
864
864
  const base = isValidRequested ? requestedPort : this.basePort;
865
865
  const port = await findAvailablePortNear(base, void 0, host);
866
- const instanceId = resolveInstanceIdOverride() || __rspack_external_node_crypto_9ba42079.randomBytes(8).toString('hex');
866
+ const override = resolveInstanceIdOverride();
867
+ const instanceId = override || __rspack_external_node_crypto_9ba42079.randomBytes(8).toString('hex');
867
868
  this.currentInstance = {
868
869
  instanceId,
869
- port
870
+ port,
871
+ instanceExplicit: void 0 !== override
870
872
  };
871
873
  return {
872
874
  port,
@@ -1157,6 +1159,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
1157
1159
  browser: devOptions.browser,
1158
1160
  mode: 'development',
1159
1161
  instanceId: currentInstance.instanceId,
1162
+ instanceExplicit: currentInstance.instanceExplicit,
1160
1163
  controlPort: bridgeControlPort,
1161
1164
  controlPath: CONTROL_WS_PATH,
1162
1165
  logsPath: bridgeLogsRelPath,
@@ -1207,6 +1210,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
1207
1210
  port,
1208
1211
  host: connectableHost,
1209
1212
  instanceId: currentInstance.instanceId,
1213
+ instanceExplicit: currentInstance.instanceExplicit,
1210
1214
  controlPort: bridgeControlPort,
1211
1215
  controlPath: CONTROL_WS_PATH,
1212
1216
  logsPath: bridgeLogsRelPath
@@ -1232,8 +1236,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
1232
1236
  readyPath: metadata.readyPath,
1233
1237
  distPath: primaryDistPath
1234
1238
  });
1235
- const requestedPort = Number(devOptions.port);
1236
- if (Number.isFinite(requestedPort) && requestedPort !== port) humanLine(portInUse(requestedPort, port));
1239
+ if (shouldWarnPortConflict(devOptions.port, port)) humanLine(portInUse(Number(devOptions.port), port));
1237
1240
  const serverConfig = {
1238
1241
  host: devServerHost,
1239
1242
  allowedHosts: 'all',
@@ -9919,7 +9919,9 @@ class ManifestLegacyWarnings {
9919
9919
  let count = 0;
9920
9920
  legacy.forEach((needle)=>{
9921
9921
  if (text.includes(needle)) {
9922
- const warn = new core_WebpackError(legacyManifestPathWarning(needle));
9922
+ const message = legacyManifestPathWarning(needle);
9923
+ humanLine(message);
9924
+ const warn = new core_WebpackError(message);
9923
9925
  warn.name = 'ManifestLegacyWarning';
9924
9926
  warn.file = 'manifest.json';
9925
9927
  compilation.warnings.push(warn);
@@ -10898,7 +10900,9 @@ class UpdateManifest {
10898
10900
  const sanitized = sanitizeFatalManifestShapes(patchedManifest, __rspack_external_node_path_c5b9b54f.dirname(this.manifestPath));
10899
10901
  patchedManifest = sanitized.manifest;
10900
10902
  for (const fix of sanitized.fixes){
10901
- const warn = new core_WebpackError(fatalManifestShapeFixed(fix.field, fix.detail));
10903
+ const message = fatalManifestShapeFixed(fix.field, fix.detail);
10904
+ humanLine(message);
10905
+ const warn = new core_WebpackError(message);
10902
10906
  warn.name = 'ManifestFatalShapeWarning';
10903
10907
  warn.file = 'manifest.json';
10904
10908
  compilation.warnings.push(warn);
@@ -11927,6 +11931,7 @@ function webpackConfig(projectStructure, devOptions) {
11927
11931
  port: devOptions.port,
11928
11932
  host: process.env.EXTENSION_DEV_SERVER_CONNECTABLE_HOST || devOptions.host,
11929
11933
  instanceId: devOptions.instanceId,
11934
+ instanceExplicit: devOptions.instanceExplicit,
11930
11935
  controlPort: devOptions.controlPort,
11931
11936
  controlPath: devOptions.controlPath,
11932
11937
  logsPath: devOptions.logsPath,
@@ -5,6 +5,7 @@ var stats_handler_namespaceObject = {};
5
5
  __webpack_require__.r(stats_handler_namespaceObject);
6
6
  __webpack_require__.d(stats_handler_namespaceObject, {
7
7
  handleStatsErrors: ()=>handleStatsErrors,
8
+ isEmitTimeWarning: ()=>isEmitTimeWarning,
8
9
  renderStatsBlocks: ()=>renderStatsBlocks,
9
10
  wrapStatsBlocks: ()=>wrapStatsBlocks
10
11
  });
@@ -33,6 +34,62 @@ function makeSanitizedConsole(brand = 'Extension.js') {
33
34
  };
34
35
  }
35
36
  const ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
37
+ const EMIT_TIME_WARNING_CODES = new Set([
38
+ 'ManifestFatalShapeWarning',
39
+ 'ManifestLegacyWarning'
40
+ ]);
41
+ function isEmitTimeWarning(warning) {
42
+ if (!warning || 'string' == typeof warning) return false;
43
+ return EMIT_TIME_WARNING_CODES.has(String(warning.code || ''));
44
+ }
45
+ function collectEmitTimeWarningTexts(stats) {
46
+ const texts = new Set();
47
+ try {
48
+ const warnings = stats.toJson?.({
49
+ all: false,
50
+ warnings: true
51
+ })?.warnings;
52
+ for (const warning of warnings || []){
53
+ if (!isEmitTimeWarning(warning)) continue;
54
+ const text = String(warning?.message ?? '').replace(ANSI_PATTERN, '').trim();
55
+ if (text) texts.add(text);
56
+ }
57
+ } catch {}
58
+ return texts;
59
+ }
60
+ function dropEmitTimeWarningBlocks(raw, excluded) {
61
+ if (0 === excluded.size) return raw;
62
+ const kept = [];
63
+ let block = null;
64
+ const flush = ()=>{
65
+ if (!block) return;
66
+ const body = block.slice(1).map((line)=>line.replace(ANSI_PATTERN, '')).join('\n').trim();
67
+ if (!excluded.has(body)) kept.push(...block);
68
+ block = null;
69
+ };
70
+ for (const line of String(raw).split('\n')){
71
+ const plain = line.replace(ANSI_PATTERN, '');
72
+ if (/^WARNING(?: in .+)?$/.test(plain)) {
73
+ flush();
74
+ block = [
75
+ line
76
+ ];
77
+ continue;
78
+ }
79
+ if (/^ERROR(?: in .+)?$/.test(plain)) {
80
+ flush();
81
+ kept.push(line);
82
+ continue;
83
+ }
84
+ if (block) {
85
+ block.push(line);
86
+ continue;
87
+ }
88
+ kept.push(line);
89
+ }
90
+ flush();
91
+ return kept.join('\n');
92
+ }
36
93
  function wrapStatsBlocks(raw) {
37
94
  const lines = String(raw || '').split('\n');
38
95
  const wrapped = [];
@@ -66,7 +123,9 @@ function renderStatsBlocks(stats, opts) {
66
123
  warnings: opts.warnings
67
124
  });
68
125
  if (!raw) return '';
69
- return wrapStatsBlocks(scrubBrand(raw));
126
+ const filtered = opts.warnings ? dropEmitTimeWarningBlocks(raw, collectEmitTimeWarningTexts(stats)) : raw;
127
+ if (!filtered.trim()) return '';
128
+ return wrapStatsBlocks(scrubBrand(filtered));
70
129
  }
71
130
  function handleStatsErrors(stats) {
72
131
  try {
package/dist/101.mjs CHANGED
@@ -8,7 +8,7 @@ import node_fs from "node:fs";
8
8
  import node_path from "node:path";
9
9
  import { getSpecialFoldersData } from "browser-extension-manifest-fields";
10
10
  import { createHash } from "node:crypto";
11
- import { fmt, browserRowValue, isDebug, artifactNoun, prefix as messaging_prefix, card } from "./349.mjs";
11
+ import { fmt, browserRowValue, isDebug, humanWarn, artifactNoun, prefix as messaging_prefix, card } from "./349.mjs";
12
12
  import { findNearestDenoConfigSync, validateDenoConfig, PROJECT_MANIFEST_FILENAMES, readProjectDependencies } from "./80.mjs";
13
13
  import { stripBom, parseJsonSafe } from "./23.mjs";
14
14
  import { readyContractPath, browserArtifactsDir, eventsPath as session_paths_eventsPath } from "./494.mjs";
@@ -80,6 +80,10 @@ function projectInstallFallbackToNpm(pmName) {
80
80
  function projectInstallScriptsDisabled(pmName) {
81
81
  return `${getLoggingPrefix('info')} Installing the project dependencies with ${pmName}…\nLifecycle scripts are disabled for safety.\nSet ${pintor.blue('EXTENSION_ALLOW_INSTALL_SCRIPTS=true')} to run them.`;
82
82
  }
83
+ function anotherDevSessionActive(browser, pid, runId) {
84
+ const run = runId ? `, run ${runId}` : '';
85
+ return `${getLoggingPrefix('warn')} Another dev session is already writing dist/${browser} (PID ${pid}${run}).\nBoth sessions rebuild the same output, so the last compile wins.\nStop the other session, or pass ${fmt.code('--instance-id')} to run them side by side.`;
86
+ }
83
87
  function buildAssetsTree(stats) {
84
88
  const statsJson = stats?.toJson?.({
85
89
  all: false,
@@ -93,6 +97,9 @@ function buildComplete(browser, distDisplayPath, totalBytes) {
93
97
  const size = 'number' == typeof totalBytes && totalBytes > 0 ? ` (${getHumanSize(totalBytes)})` : '';
94
98
  return `${getLoggingPrefix('success')} ${noun} built for production in ${pintor.underline(distDisplayPath)}${size}.`;
95
99
  }
100
+ function buildShareHint() {
101
+ return `${getLoggingPrefix('info')} Send this build to someone for review: ` + pintor.underline('https://docs.extension.dev/share/unpublished-build-for-review?utm_source=cli-build');
102
+ }
96
103
  function buildFailed(errorCount) {
97
104
  const count = Math.max(1, Math.floor(errorCount || 1));
98
105
  const noun = 1 === count ? 'error' : 'errors';
@@ -627,7 +634,7 @@ async function config_loader_isUsingExperimentalConfig(projectPath) {
627
634
  }
628
635
  return false;
629
636
  }
630
- var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.22","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
637
+ var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.24","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
631
638
  function asAbsolute(p) {
632
639
  return __rspack_external_node_path_c5b9b54f.isAbsolute(p) ? p : __rspack_external_node_path_c5b9b54f.resolve(p);
633
640
  }
@@ -1626,6 +1633,10 @@ function browserRunnerDisabled(args) {
1626
1633
  ]
1627
1634
  });
1628
1635
  }
1636
+ function shouldWarnPortConflict(requested, actual) {
1637
+ const requestedPort = Number(requested);
1638
+ return Number.isFinite(requestedPort) && 0 !== requestedPort && requestedPort !== actual;
1639
+ }
1629
1640
  function portInUse(requestedPort, newPort) {
1630
1641
  return `${messages_getLoggingPrefix('warn')} Port ${requestedPort} is in use.\nThe dev server listens on port ${newPort} instead.`;
1631
1642
  }
@@ -1857,6 +1868,15 @@ function getRunIdForSession(metadataDir) {
1857
1868
  function getSessionRunId(packageJsonDir, browser) {
1858
1869
  return getRunIdForSession(getPlaywrightMetadataDir(packageJsonDir, browser));
1859
1870
  }
1871
+ function deriveDistExtensionId(browser, distPath) {
1872
+ try {
1873
+ if (!__rspack_external_node_fs_5ea92f0c.existsSync(__rspack_external_node_path_c5b9b54f.join(distPath, 'manifest.json'))) return;
1874
+ const id = isGeckoBasedBrowser(browser) ? geckoExtensionId(distPath) : chromiumExtensionId(distPath);
1875
+ return id || void 0;
1876
+ } catch {
1877
+ return;
1878
+ }
1879
+ }
1860
1880
  function readManifestProvenance(manifestPath) {
1861
1881
  try {
1862
1882
  const manifest = parseJsonSafe(__rspack_external_node_fs_5ea92f0c.readFileSync(manifestPath, 'utf-8'));
@@ -1882,6 +1902,35 @@ function writeJsonAtomic(filePath, value) {
1882
1902
  __rspack_external_node_fs_5ea92f0c.renameSync(tmpPath, filePath);
1883
1903
  } catch {}
1884
1904
  }
1905
+ function detectLiveDevSessionOwner(readyPath, isAlive = (pid)=>{
1906
+ try {
1907
+ process.kill(pid, 0);
1908
+ return true;
1909
+ } catch {
1910
+ return false;
1911
+ }
1912
+ }) {
1913
+ try {
1914
+ if (!__rspack_external_node_fs_5ea92f0c.existsSync(readyPath)) return null;
1915
+ const prev = JSON.parse(__rspack_external_node_fs_5ea92f0c.readFileSync(readyPath, 'utf-8'));
1916
+ if (prev?.command !== 'dev') return null;
1917
+ if ('number' != typeof prev.pid || prev.pid === process.pid) return null;
1918
+ if ('ready' !== prev.status && 'starting' !== prev.status) return null;
1919
+ if (!isAlive(prev.pid)) return null;
1920
+ return {
1921
+ pid: prev.pid,
1922
+ runId: 'string' == typeof prev.runId ? prev.runId : '',
1923
+ instanceId: 'string' == typeof prev.instanceId ? prev.instanceId : void 0,
1924
+ instanceExplicit: true === prev.instanceExplicit
1925
+ };
1926
+ } catch {
1927
+ return null;
1928
+ }
1929
+ }
1930
+ function shouldWarnDevOverDev(owner, my) {
1931
+ if (owner.instanceExplicit && my.instanceExplicit && owner.instanceId && my.instanceId && owner.instanceId !== my.instanceId) return false;
1932
+ return true;
1933
+ }
1885
1934
  function getPlaywrightMetadataDir(packageJsonDir, browser) {
1886
1935
  return asAbsolute(browserArtifactsDir(packageJsonDir, browser));
1887
1936
  }
@@ -1897,23 +1946,13 @@ function createPlaywrightMetadataWriter(options) {
1897
1946
  }
1898
1947
  return null;
1899
1948
  };
1900
- const foreignLiveDevSession = (()=>{
1901
- if ('dev' === options.command) return null;
1902
- try {
1903
- if (!__rspack_external_node_fs_5ea92f0c.existsSync(readyPath)) return null;
1904
- const prev = JSON.parse(__rspack_external_node_fs_5ea92f0c.readFileSync(readyPath, 'utf-8'));
1905
- if (prev?.command !== 'dev') return null;
1906
- if ('number' != typeof prev.pid || prev.pid === process.pid) return null;
1907
- if ('ready' !== prev.status && 'starting' !== prev.status) return null;
1908
- process.kill(prev.pid, 0);
1909
- return {
1910
- pid: prev.pid
1911
- };
1912
- } catch {
1913
- return null;
1914
- }
1915
- })();
1949
+ const liveOwner = detectLiveDevSessionOwner(readyPath);
1950
+ const foreignLiveDevSession = 'dev' !== options.command && liveOwner ? liveOwner : null;
1916
1951
  if (foreignLiveDevSession) console.warn(`[extension] a live dev session (pid ${foreignLiveDevSession.pid}) owns ${readyPath}; this ${options.command} run will not rewrite the session's ready.json/events.ndjson. The output dir is shared, so the dev browser may pick up freshly ${options.command}-built files. Stop the dev session first for a clean ${options.command} receipt.`);
1952
+ if ('dev' === options.command && liveOwner && shouldWarnDevOverDev(liveOwner, {
1953
+ instanceId: options.instanceId,
1954
+ instanceExplicit: options.instanceExplicit
1955
+ })) humanWarn(anotherDevSessionActive(options.browser, liveOwner.pid, liveOwner.runId));
1917
1956
  const toManagedRecords = (dirs)=>Array.isArray(dirs) && dirs.length > 0 ? managedExtensionRecords(options.browser, dirs) : void 0;
1918
1957
  let managedExtensions = toManagedRecords(options.managedExtensionDirs);
1919
1958
  const base = {
@@ -1928,6 +1967,9 @@ function createPlaywrightMetadataWriter(options) {
1928
1967
  port: toPort(options.port),
1929
1968
  host: options.host,
1930
1969
  instanceId: options.instanceId,
1970
+ ...options.instanceExplicit ? {
1971
+ instanceExplicit: true
1972
+ } : {},
1931
1973
  controlPort: toPort(options.controlPort),
1932
1974
  controlPath: options.controlPath,
1933
1975
  logsPath: options.logsPath,
@@ -1948,6 +1990,8 @@ function createPlaywrightMetadataWriter(options) {
1948
1990
  if (extra?.code) payload.code = extra.code;
1949
1991
  if (extra?.message) payload.message = extra.message;
1950
1992
  if (managedExtensions) payload.managedExtensions = managedExtensions;
1993
+ const derivedExtensionId = deriveDistExtensionId(options.browser, options.distPath);
1994
+ if (derivedExtensionId) payload.extensionId = derivedExtensionId;
1951
1995
  try {
1952
1996
  if (__rspack_external_node_fs_5ea92f0c.existsSync(readyPath)) {
1953
1997
  const prev = JSON.parse(__rspack_external_node_fs_5ea92f0c.readFileSync(readyPath, 'utf-8'));
@@ -1956,6 +2000,7 @@ function createPlaywrightMetadataWriter(options) {
1956
2000
  if (!payload.managedExtensions && Array.isArray(prev.managedExtensions)) payload.managedExtensions = prev.managedExtensions;
1957
2001
  if ('string' == typeof prev.profilePath) payload.profilePath = prev.profilePath;
1958
2002
  if ('number' == typeof prev.browserPid) payload.browserPid = prev.browserPid;
2003
+ if ('string' == typeof prev.extensionId && prev.extensionId) payload.extensionId = prev.extensionId;
1959
2004
  if ('string' == typeof prev.browserExitedAt) {
1960
2005
  payload.browserExitedAt = prev.browserExitedAt;
1961
2006
  payload.browserExitCode = prev.browserExitCode ?? null;
@@ -2068,6 +2113,7 @@ class PlaywrightPlugin {
2068
2113
  port: options.port,
2069
2114
  host: options.host,
2070
2115
  instanceId: options.instanceId,
2116
+ instanceExplicit: options.instanceExplicit,
2071
2117
  controlPort: options.controlPort,
2072
2118
  controlPath: options.controlPath,
2073
2119
  logsPath: options.logsPath,
@@ -2295,4 +2341,4 @@ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher
2295
2341
  await browserLauncher(resolvedOpts);
2296
2342
  metadata.writeReady();
2297
2343
  }
2298
- export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, PlaywrightPlugin, asAbsolute, assertNoManagedDependencyConflicts, authorInstallNotice, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserLaunchFailed, browserRunnerDisabled, buildAssetsTree, buildCommandFailed, buildComplete, buildFailed, buildWarningsDetails, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, debugBrowser, debugContextPath, debugDirs, debugExtensionsToLoad, debugOutputPath, devCommandFailed, devServerStartTimeout, downloadingText, extensionJsRunnerError, extensionLoadRecovered, extensionLoadStillRefused, extensionPreview, failedToDownloadOrExtractZIPFileError, getDirs, getDistPath, getProjectStructure, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, invalidRemoteZip, isChromiumBasedBrowser, isGeckoBasedBrowser, loadBrowserConfig, loadCommandConfig, loadCustomConfig, localZipNotFound, manifestInvalidJson, messages_ready, needsInstall, noCompanionExtensionsResolved, noEntrypointsDetected, normalizeBrowser, notAZipArchive, package_namespaceObject, packagingDistributionFiles, packagingSourceFiles, portInUse, projectInstallFallbackToNpm, projectInstallScriptsDisabled, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, sanitize, spacerLine, toPosixPath, treeWithDistFilesBrowser, treeWithSourceAndDistFiles, treeWithSourceFiles, unpackagedSuccessfully, unpackagingExtension, writingTypeDefinitions, writingTypeDefinitionsError, zipArtifactReady };
2344
+ export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, PlaywrightPlugin, asAbsolute, assertNoManagedDependencyConflicts, authorInstallNotice, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserLaunchFailed, browserRunnerDisabled, buildAssetsTree, buildCommandFailed, buildComplete, buildFailed, buildShareHint, buildWarningsDetails, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, debugBrowser, debugContextPath, debugDirs, debugExtensionsToLoad, debugOutputPath, devCommandFailed, devServerStartTimeout, downloadingText, extensionJsRunnerError, extensionLoadRecovered, extensionLoadStillRefused, extensionPreview, failedToDownloadOrExtractZIPFileError, getDirs, getDistPath, getProjectStructure, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, invalidRemoteZip, isChromiumBasedBrowser, isGeckoBasedBrowser, loadBrowserConfig, loadCommandConfig, loadCustomConfig, localZipNotFound, manifestInvalidJson, messages_ready, needsInstall, noCompanionExtensionsResolved, noEntrypointsDetected, normalizeBrowser, notAZipArchive, package_namespaceObject, packagingDistributionFiles, packagingSourceFiles, portInUse, projectInstallFallbackToNpm, projectInstallScriptsDisabled, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, sanitize, shouldWarnPortConflict, spacerLine, toPosixPath, treeWithDistFilesBrowser, treeWithSourceAndDistFiles, treeWithSourceFiles, unpackagedSuccessfully, unpackagingExtension, writingTypeDefinitions, writingTypeDefinitionsError, zipArtifactReady };
package/dist/349.mjs CHANGED
@@ -22,6 +22,17 @@ function prefix(type) {
22
22
  if ('debug' === type) return pintor.dim(pintor.gray(DEBUG_GLYPH));
23
23
  return pintor.gray(GLYPH);
24
24
  }
25
+ const MACHINE_OUTPUT_VALUES = new Set([
26
+ 'json',
27
+ 'ndjson'
28
+ ]);
29
+ function isMachineOutput() {
30
+ return MACHINE_OUTPUT_VALUES.has(String(process.env.EXTENSION_OUTPUT || '').trim().toLowerCase());
31
+ }
32
+ function humanWarn(...parts) {
33
+ if (isMachineOutput()) return;
34
+ console.warn(...parts);
35
+ }
25
36
  const fmt = {
26
37
  heading: (title)=>pintor.underline(pintor.blue(title)),
27
38
  label: (key)=>pintor.gray(key.toUpperCase()),
@@ -256,4 +267,4 @@ const ENVELOPE = {
256
267
  }, extras);
257
268
  }
258
269
  };
259
- export { CODES, ENVELOPE, artifactNoun, browserRowValue, card, claimCardKey, fmt, isDebug, prefix };
270
+ export { CODES, ENVELOPE, artifactNoun, browserRowValue, card, claimCardKey, fmt, humanWarn, isDebug, isMachineOutput, prefix };
package/dist/839.mjs CHANGED
@@ -4,8 +4,8 @@ import { execFileSync, spawn, spawnSync as external_node_child_process_spawnSync
4
4
  import { buildExecEnv, detectPackageManagerFromLockfile } from "prefers-yarn";
5
5
  import "pintor";
6
6
  import { EventEmitter } from "node:events";
7
- import { browserRowValue, isDebug, CODES, ENVELOPE, prefix as messaging_prefix, claimCardKey, card } from "./349.mjs";
8
- import { package_namespaceObject, buildWarningsDetails, sanitize, buildFailed, getDirs, zipArtifactReady, projectInstallFallbackToNpm, assertNoManagedDependencyConflicts, debugDirs, browserLaunchFailed, extensionLoadRecovered, extensionLoadStillRefused, writingTypeDefinitionsError, projectInstallScriptsDisabled, authorInstallNotice, getSpecialFoldersDataForProjectRoot, buildAssetsTree, loadCommandConfig, needsInstall, buildCommandFailed, writingTypeDefinitions, buildComplete, normalizeBrowser, debugBrowser, debugOutputPath, loadCustomConfig, devCommandFailed, getProjectStructure, getDistPath, resolveCompanionExtensionsConfig, loadBrowserConfig } from "./101.mjs";
7
+ import { browserRowValue, ENVELOPE, CODES, prefix as messaging_prefix, card, isDebug, claimCardKey, isMachineOutput } from "./349.mjs";
8
+ import { package_namespaceObject, buildWarningsDetails, sanitize, buildFailed, getDirs, zipArtifactReady, projectInstallFallbackToNpm, assertNoManagedDependencyConflicts, debugDirs, browserLaunchFailed, extensionLoadRecovered, extensionLoadStillRefused, writingTypeDefinitionsError, projectInstallScriptsDisabled, authorInstallNotice, getSpecialFoldersDataForProjectRoot, buildAssetsTree, loadCommandConfig, needsInstall, buildCommandFailed, writingTypeDefinitions, buildComplete, normalizeBrowser, debugBrowser, debugOutputPath, loadCustomConfig, devCommandFailed, getProjectStructure, getDistPath, resolveCompanionExtensionsConfig, buildShareHint, loadBrowserConfig } from "./101.mjs";
9
9
  import { stripBom, parseJsonSafe } from "./23.mjs";
10
10
  import { hasProjectDependency, findNearestProjectManifestDirSync } from "./80.mjs";
11
11
  import { buildSummaryPath, ensureSessionArtifactsIgnoreFile } from "./494.mjs";
@@ -19,13 +19,6 @@ import * as __rspack_external_node_path_c5b9b54f from "node:path";
19
19
  import * as __rspack_external_node_fs_promises_153e37e0 from "node:fs/promises";
20
20
  const MAX_OUTPUT_CHARS = 2000;
21
21
  const ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
22
- const MACHINE_OUTPUT_VALUES = new Set([
23
- 'json',
24
- 'ndjson'
25
- ]);
26
- function isMachineOutput() {
27
- return MACHINE_OUTPUT_VALUES.has(String(process.env.EXTENSION_OUTPUT || '').trim().toLowerCase());
28
- }
29
22
  function isLifecycleStreamEnabled() {
30
23
  return isMachineOutput();
31
24
  }
@@ -787,6 +780,18 @@ async function generateExtensionTypes(manifestDir, packageJsonDir) {
787
780
  }
788
781
  }
789
782
  }
783
+ const ARTIFACTS_KEY = '__extensionJsZipArtifacts';
784
+ function recordZipArtifact(carrier, artifact) {
785
+ if (!carrier || 'object' != typeof carrier) return;
786
+ const host = carrier;
787
+ if (!Array.isArray(host[ARTIFACTS_KEY])) host[ARTIFACTS_KEY] = [];
788
+ host[ARTIFACTS_KEY].push(artifact);
789
+ }
790
+ function getZipArtifacts(carrier) {
791
+ if (!carrier || 'object' != typeof carrier) return [];
792
+ const host = carrier;
793
+ return Array.isArray(host[ARTIFACTS_KEY]) ? host[ARTIFACTS_KEY] : [];
794
+ }
790
795
  function hasDependency(projectPath, packageName) {
791
796
  return hasProjectDependency(projectPath, packageName);
792
797
  }
@@ -919,18 +924,6 @@ function writeTsConfig(projectPath) {
919
924
  mode: 'development'
920
925
  }), null, 2));
921
926
  }
922
- const ARTIFACTS_KEY = '__extensionJsZipArtifacts';
923
- function recordZipArtifact(carrier, artifact) {
924
- if (!carrier || 'object' != typeof carrier) return;
925
- const host = carrier;
926
- if (!Array.isArray(host[ARTIFACTS_KEY])) host[ARTIFACTS_KEY] = [];
927
- host[ARTIFACTS_KEY].push(artifact);
928
- }
929
- function getZipArtifacts(carrier) {
930
- if (!carrier || 'object' != typeof carrier) return [];
931
- const host = carrier;
932
- return Array.isArray(host[ARTIFACTS_KEY]) ? host[ARTIFACTS_KEY] : [];
933
- }
934
927
  function collapseHomeDir(value) {
935
928
  const home = __rspack_external_node_os_74b4b876.homedir();
936
929
  if (!home || !value.startsWith(home)) return value;
@@ -992,7 +985,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
992
985
  if (buildOptions?.install !== false) await ensureUserProjectDependencies(packageJsonDir);
993
986
  ensureTypeScriptConfig(manifestDir);
994
987
  if (isUsingTypeScript(manifestDir)) await generateExtensionTypes(manifestDir, packageJsonDir);
995
- const [{ rspack }, { merge }, { handleStatsErrors }, { default: webpackConfig }] = await Promise.all([
988
+ const [{ rspack }, { merge }, { handleStatsErrors, isEmitTimeWarning }, { default: webpackConfig }] = await Promise.all([
996
989
  import("@rspack/core"),
997
990
  import("webpack-merge"),
998
991
  import("./0~stats-handler.mjs").then((m)=>m.stats_handler_namespaceObject),
@@ -1100,7 +1093,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
1100
1093
  __rspack_external_node_fs_5ea92f0c.writeFileSync(summaryFile, JSON.stringify(summary));
1101
1094
  } catch {}
1102
1095
  if (summary.warnings_count > 0) {
1103
- const warningDetails = buildWarningsDetails(info?.warnings || []);
1096
+ const warningDetails = buildWarningsDetails((info?.warnings || []).filter((warning)=>!isEmitTimeWarning(warning)));
1104
1097
  if (warningDetails) humanLine(warningDetails);
1105
1098
  }
1106
1099
  const distDisplay = relativeToCwd(distPath) || collapseHomeDir(distPath);
@@ -1109,6 +1102,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
1109
1102
  const zipDisplay = relativeToCwd(artifact.path) || artifact.path;
1110
1103
  humanLine(zipArtifactReady(zipDisplay, artifact.size));
1111
1104
  }
1105
+ humanLine(buildShareHint());
1112
1106
  resolve();
1113
1107
  }
1114
1108
  });
@@ -1,7 +1,7 @@
1
- import { type Envelope } from '../lib/messaging';
1
+ import { type Envelope, isMachineOutput } from '../lib/messaging';
2
2
  export type LifecycleCommand = 'dev' | 'start' | 'preview';
3
3
  export type LifecycleStatus = 'starting' | 'compiled' | 'recompiled' | 'compile-failed' | 'ready' | 'browser-exited' | 'failed';
4
- export declare function isMachineOutput(): boolean;
4
+ export { isMachineOutput };
5
5
  export declare function isLifecycleStreamEnabled(): boolean;
6
6
  export declare function humanLine(line: string): void;
7
7
  export declare function stripAnsi(input: string): string;
@@ -5,6 +5,7 @@ export declare function browserRunnerDisabled(args: {
5
5
  readyPath: string;
6
6
  distPath?: string;
7
7
  }): string;
8
+ export declare function shouldWarnPortConflict(requested: unknown, actual: number): boolean;
8
9
  export declare function portInUse(requestedPort: number, newPort: number): string;
9
10
  export declare function extensionJsRunnerError(error: unknown): string;
10
11
  export declare function autoExitModeEnabled(ms: number): string;
@@ -5,6 +5,7 @@ export interface PortAllocation {
5
5
  interface LocalInstanceInfo {
6
6
  instanceId: string;
7
7
  port: number;
8
+ instanceExplicit: boolean;
8
9
  }
9
10
  export declare class PortManager {
10
11
  private readonly basePort;
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * What the injected Safari packager reports back about the app it produced.
3
3
  * `bundleIdDerived` is the load-bearing one: a generated `dev.extensionjs.*`
4
- * identifier is fine locally and rejected by Apple for distribution, and the
5
- * only other place that fact appeared was a human log line.
4
+ * identifier comes from the app name, so every project built from the same
5
+ * source shares it and the first registration takes it.
6
6
  */
7
7
  export interface SafariPackageSummary {
8
8
  appName?: string;
@@ -15,8 +15,10 @@ export declare function browserLaunchFailed(browser: DevOptions['browser'], reas
15
15
  export declare function authorInstallNotice(target: string): string;
16
16
  export declare function projectInstallFallbackToNpm(pmName: string): string;
17
17
  export declare function projectInstallScriptsDisabled(pmName: string): string;
18
+ export declare function anotherDevSessionActive(browser: string, pid: number, runId: string): string;
18
19
  export declare function buildAssetsTree(stats: Stats | undefined): string;
19
20
  export declare function buildComplete(browser: DevOptions['browser'], distDisplayPath: string, totalBytes?: number): string;
21
+ export declare function buildShareHint(): string;
20
22
  export declare function buildFailed(errorCount: number): string;
21
23
  type LooseBuildWarning = string | null | undefined | {
22
24
  message?: unknown;
@@ -1,6 +1,10 @@
1
1
  export type Channel = 'info' | 'success' | 'warn' | 'error' | 'debug';
2
2
  export declare function isDebug(): boolean;
3
3
  export declare function prefix(type: Channel): string;
4
+ export declare function isMachineOutput(): boolean;
5
+ export declare function humanLine(...parts: unknown[]): void;
6
+ export declare function humanWarn(...parts: unknown[]): void;
7
+ export declare function humanError(...parts: unknown[]): void;
4
8
  export declare const fmt: {
5
9
  heading: (title: string) => string;
6
10
  label: (key: string) => string;
@@ -5,7 +5,19 @@ export interface StatsToStringLike {
5
5
  errors?: boolean;
6
6
  warnings?: boolean;
7
7
  }) => string;
8
+ toJson?: (options?: {
9
+ all?: boolean;
10
+ warnings?: boolean;
11
+ }) => {
12
+ warnings?: Array<{
13
+ code?: unknown;
14
+ message?: unknown;
15
+ }>;
16
+ };
8
17
  }
18
+ export declare function isEmitTimeWarning(warning: {
19
+ code?: unknown;
20
+ } | string | null | undefined): boolean;
9
21
  export declare function wrapStatsBlocks(raw: string): string;
10
22
  export declare function renderStatsBlocks(stats: StatsToStringLike, opts: {
11
23
  errors: boolean;
package/dist/module.d.ts CHANGED
@@ -7,4 +7,5 @@ import { type BrowserController, type BrowserLauncherFn, type BrowserLaunchOptio
7
7
  import type { ReloadInstruction, ReloadType } from './plugin-reload';
8
8
  import type { CompanionExtensionsConfig } from './plugin-special-folders/folder-extensions/types';
9
9
  import type { BrowserConfig, BrowserType, BuildOptions, DevOptions, FileConfig, Manifest, PreviewOptions, SafariPackagerFn, SafariPackagerOverrides, StartOptions } from './types';
10
+ export { loadCommandConfig } from './lib/config-loader';
10
11
  export { extensionBuild, type BuildOptions, extensionDev, type DevOptions, extensionPreview, type PreviewOptions, type StartOptions, type FileConfig, type BrowserConfig, type BrowserType, type CompanionExtensionsConfig, type Manifest, type BuildSummary, type SafariPackageSummary, type SafariPackagerFn, type SafariPackagerOverrides, BuildEmitter, type CompiledEvent, type BuildErrorEvent, type ReloadType, type ReloadInstruction, type BrowserLauncherFn, type BrowserLaunchOptions, type BrowserController };
package/dist/module.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
2
2
  export { BuildEmitter, extensionBuild, extensionDev } from "./839.mjs";
3
- export { extensionPreview } from "./101.mjs";
3
+ export { extensionPreview, loadCommandConfig } from "./101.mjs";
@@ -22,6 +22,7 @@ export type ReadyMetadata = {
22
22
  code?: string;
23
23
  message?: string;
24
24
  instanceId?: string;
25
+ instanceExplicit?: boolean;
25
26
  controlPort?: number | null;
26
27
  controlPath?: string;
27
28
  logsPath?: string;
@@ -32,6 +33,7 @@ export type ReadyMetadata = {
32
33
  toolchainVersion: string;
33
34
  extensionName?: string;
34
35
  extensionVersion?: string;
36
+ extensionId?: string;
35
37
  browserExitedAt?: string;
36
38
  browserExitCode?: number | null;
37
39
  runtime?: 'attached';
@@ -57,6 +59,7 @@ type WriterOptions = {
57
59
  port?: number | string | null;
58
60
  host?: string;
59
61
  instanceId?: string;
62
+ instanceExplicit?: boolean;
60
63
  controlPort?: number | string | null;
61
64
  controlPath?: string;
62
65
  logsPath?: string;
@@ -72,6 +75,7 @@ type PluginOptions = {
72
75
  host?: string;
73
76
  command?: PlaywrightAutomationCommand;
74
77
  instanceId?: string;
78
+ instanceExplicit?: boolean;
75
79
  controlPort?: number | string | null;
76
80
  controlPath?: string;
77
81
  logsPath?: string;
@@ -79,6 +83,17 @@ type PluginOptions = {
79
83
  };
80
84
  export declare function formatStatsErrors(errors: unknown): string[];
81
85
  export declare function getSessionRunId(packageJsonDir: string, browser: string): string;
86
+ export interface LiveDevSessionOwner {
87
+ pid: number;
88
+ runId: string;
89
+ instanceId?: string;
90
+ instanceExplicit?: boolean;
91
+ }
92
+ export declare function detectLiveDevSessionOwner(readyPath: string, isAlive?: (pid: number) => boolean): LiveDevSessionOwner | null;
93
+ export declare function shouldWarnDevOverDev(owner: LiveDevSessionOwner, my: {
94
+ instanceId?: string;
95
+ instanceExplicit?: boolean;
96
+ }): boolean;
82
97
  export declare function getPlaywrightMetadataDir(packageJsonDir: string, browser: string): AbsolutePath;
83
98
  export declare function createPlaywrightMetadataWriter(options: WriterOptions): {
84
99
  metadataDir: AbsolutePath;
package/dist/types.d.ts CHANGED
@@ -247,6 +247,10 @@ export interface PreviewOptions extends BrowserOptionsBase {
247
247
  * Internal auto-generated instance ID, not user-configurable.
248
248
  */
249
249
  instanceId?: string;
250
+ /**
251
+ * Internal: true when the instance ID came from the user, not autogenerated.
252
+ */
253
+ instanceExplicit?: boolean;
250
254
  /**
251
255
  * Dry run mode (no browser launch) for diagnostics.
252
256
  */
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "runtime"
44
44
  ],
45
45
  "name": "extension-develop",
46
- "version": "4.0.22",
46
+ "version": "4.0.24",
47
47
  "description": "Develop, build, preview, and package Extension.js projects.",
48
48
  "author": {
49
49
  "name": "Cezar Augusto",