@stencil/cli 5.0.0-alpha.5 → 5.0.0-alpha.6

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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import * as _$_stencil_core_compiler0 from "@stencil/core/compiler";
1
+ import * as d from "@stencil/core/compiler";
2
2
  import { LogLevel } from "@stencil/core/compiler";
3
3
 
4
4
  //#region src/types.d.ts
@@ -123,7 +123,7 @@ declare const createConfigFlags: (init?: Partial<ConfigFlags>) => ConfigFlags;
123
123
  declare const parseFlags: (args: string[]) => ConfigFlags;
124
124
  //#endregion
125
125
  //#region src/load-compiler.d.ts
126
- type CoreCompiler = typeof _$_stencil_core_compiler0;
126
+ type CoreCompiler = typeof import('@stencil/core/compiler');
127
127
  //#endregion
128
128
  //#region src/run.d.ts
129
129
  /**
@@ -136,7 +136,7 @@ type CoreCompiler = typeof _$_stencil_core_compiler0;
136
136
  * @param init initial CLI options
137
137
  * @returns an empty promise
138
138
  */
139
- declare const run: (init: _$_stencil_core_compiler0.CliInitOptions) => Promise<any>;
139
+ declare const run: (init: d.CliInitOptions) => Promise<any>;
140
140
  /**
141
141
  * Run a specified task
142
142
  *
@@ -148,6 +148,6 @@ declare const run: (init: _$_stencil_core_compiler0.CliInitOptions) => Promise<a
148
148
  * @public
149
149
  * @returns a void promise
150
150
  */
151
- declare const runTask: (coreCompiler: CoreCompiler, config: _$_stencil_core_compiler0.Config, task: TaskCommand, sys: _$_stencil_core_compiler0.CompilerSystem, flags?: ConfigFlags) => Promise<void>;
151
+ declare const runTask: (coreCompiler: CoreCompiler, config: d.Config, task: TaskCommand, sys: d.CompilerSystem, flags?: ConfigFlags) => Promise<void>;
152
152
  //#endregion
153
153
  export { BOOLEAN_CLI_FLAGS, type ConfigFlags, type TaskCommand, createConfigFlags, parseFlags, run, runTask };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LOG_LEVELS } from "@stencil/core/compiler";
2
2
  import { buildError, catchError, hasError, isFunction, isOutputTargetDocs, isOutputTargetSsr, isOutputTargetWww, isString, normalizePath, readOnlyArrayHasStringMember, result, shouldIgnoreError, toCamelCase, validateComponentTag } from "@stencil/core/compiler/utils";
3
- import { isAbsolute, join, parse, relative } from "path";
3
+ import { dirname, isAbsolute, join, parse, relative } from "path";
4
4
  import ts from "typescript";
5
5
  import { start } from "@stencil/dev-server";
6
6
  //#region src/config-flags.ts
@@ -853,6 +853,57 @@ const encapsulationApiRule = {
853
853
  }
854
854
  };
855
855
  //#endregion
856
+ //#region src/migrations/rules/external-runtime.ts
857
+ /**
858
+ * Migration rule for `externalRuntime` on `standalone` output targets.
859
+ *
860
+ * In Stencil v5, `externalRuntime` defaults to `false` (was `true` in v4).
861
+ * Explicit `externalRuntime: false` is now redundant and can be removed.
862
+ */
863
+ const externalRuntimeRule = {
864
+ id: "external-runtime",
865
+ name: "externalRuntime Default Change",
866
+ description: "Remove redundant 'externalRuntime: false' from standalone output targets - false is now the default",
867
+ fromVersion: "4.x",
868
+ toVersion: "5.x",
869
+ detect(sourceFile) {
870
+ const matches = [];
871
+ const visit = (node) => {
872
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === "externalRuntime" && node.initializer.kind === ts.SyntaxKind.FalseKeyword) {
873
+ const parent = node.parent;
874
+ if (ts.isObjectLiteralExpression(parent)) {
875
+ if (parent.properties.some((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "type" && ts.isStringLiteral(p.initializer) && p.initializer.text === "standalone")) {
876
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
877
+ matches.push({
878
+ node,
879
+ message: "'externalRuntime: false' is now the default - this property can be removed",
880
+ line: line + 1,
881
+ column: character + 1
882
+ });
883
+ }
884
+ }
885
+ }
886
+ ts.forEachChild(node, visit);
887
+ };
888
+ visit(sourceFile);
889
+ return matches;
890
+ },
891
+ transform(sourceFile, matches) {
892
+ if (matches.length === 0) return sourceFile.getFullText();
893
+ let text = sourceFile.getFullText();
894
+ for (const match of [...matches].reverse()) {
895
+ const node = match.node;
896
+ const start = node.getFullStart();
897
+ const end = node.getEnd();
898
+ let removeEnd = end;
899
+ const trailingComma = text.slice(end).match(/^\s*,/);
900
+ if (trailingComma) removeEnd = end + trailingComma[0].length;
901
+ text = text.slice(0, start) + text.slice(removeEnd);
902
+ }
903
+ return text;
904
+ }
905
+ };
906
+ //#endregion
856
907
  //#region src/migrations/rules/form-associated.ts
857
908
  /**
858
909
  * Migration rule for formAssociated → @AttachInternals.
@@ -1050,7 +1101,7 @@ const globalStyleInjectRule = {
1050
1101
  }
1051
1102
  }
1052
1103
  if (end !== -1) text = text.slice(0, start) + text.slice(end);
1053
- text = cleanupEmptyExtras(text);
1104
+ text = cleanupEmptyExtras$1(text);
1054
1105
  return text;
1055
1106
  }
1056
1107
  };
@@ -1073,7 +1124,7 @@ function findOutputTargetsEnd(sourceFile) {
1073
1124
  * @param text The source text to clean up
1074
1125
  * @returns The cleaned up text with empty extras removed
1075
1126
  */
1076
- function cleanupEmptyExtras(text) {
1127
+ function cleanupEmptyExtras$1(text) {
1077
1128
  return text.replace(/,?\s*extras\s*:\s*\{\s*\},?/g, "");
1078
1129
  }
1079
1130
  /**
@@ -1115,6 +1166,219 @@ function addGlobalStyleOutputTarget(text, sourceFile, injectValue) {
1115
1166
  return text.slice(0, insertPos) + insertion + text.slice(insertPos);
1116
1167
  }
1117
1168
  //#endregion
1169
+ //#region src/migrations/rules/hash-file-names.ts
1170
+ /**
1171
+ * Migration rule for `hashFileNames` and `hashedFileNameLength` config options.
1172
+ *
1173
+ * In Stencil v5, these are no longer top-level config options. They belong on
1174
+ * the `loader-bundle` and `www` output targets, which are the only outputs that
1175
+ * are served directly in the browser and benefit from content-hash caching.
1176
+ *
1177
+ * This migration:
1178
+ * 1. Removes them from the top-level config
1179
+ * 2. Injects them into any `loader-bundle` and `www` output targets found in the same file
1180
+ */
1181
+ const hashFileNamesRule = {
1182
+ id: "hash-file-names",
1183
+ name: "Hash File Names Config Move",
1184
+ description: "Move hashFileNames and hashedFileNameLength from top-level config to loader-bundle and www output targets",
1185
+ fromVersion: "4.x",
1186
+ toVersion: "5.x",
1187
+ detect(sourceFile) {
1188
+ const matches = [];
1189
+ const visit = (node) => {
1190
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && (node.name.text === "hashFileNames" || node.name.text === "hashedFileNameLength")) {
1191
+ const parent = node.parent;
1192
+ if (ts.isObjectLiteralExpression(parent)) {
1193
+ if (!parent.properties.some((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "type")) {
1194
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
1195
+ matches.push({
1196
+ node,
1197
+ message: `'${node.name.text}' is no longer a top-level config option. Move it to your 'loader-bundle' and/or 'www' output targets.`,
1198
+ line: line + 1,
1199
+ column: character + 1
1200
+ });
1201
+ }
1202
+ }
1203
+ }
1204
+ ts.forEachChild(node, visit);
1205
+ };
1206
+ visit(sourceFile);
1207
+ return matches;
1208
+ },
1209
+ transform(sourceFile, matches) {
1210
+ if (matches.length === 0) return sourceFile.getFullText();
1211
+ const fullText = sourceFile.getFullText();
1212
+ const propsToInject = matches.map((m) => {
1213
+ const node = m.node;
1214
+ return {
1215
+ name: node.name.text,
1216
+ value: node.initializer.getText(sourceFile)
1217
+ };
1218
+ });
1219
+ const TARGET_TYPES = new Set(["loader-bundle", "www"]);
1220
+ const insertionsByPos = /* @__PURE__ */ new Map();
1221
+ const visit = (node) => {
1222
+ if (ts.isObjectLiteralExpression(node)) {
1223
+ if (node.properties.find((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "type" && ts.isStringLiteral(p.initializer) && TARGET_TYPES.has(p.initializer.text))) {
1224
+ const existingPropNames = new Set(node.properties.filter((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name)).map((p) => p.name.text));
1225
+ const objStart = node.getStart(sourceFile);
1226
+ const objLineStart = fullText.lastIndexOf("\n", objStart) + 1;
1227
+ const propIndent = (fullText.slice(objLineStart, objStart).match(/^(\s*)/)?.[1] ?? "") + " ";
1228
+ const closingBracePos = node.getEnd() - 1;
1229
+ const isMultiLine = fullText.slice(objStart, node.getEnd()).includes("\n");
1230
+ let insertPos;
1231
+ if (isMultiLine) insertPos = fullText.lastIndexOf("\n", closingBracePos - 1);
1232
+ else {
1233
+ insertPos = closingBracePos;
1234
+ while (insertPos > 0 && fullText[insertPos - 1] === " ") insertPos--;
1235
+ }
1236
+ const existing = insertionsByPos.get(insertPos) ?? [];
1237
+ for (const prop of propsToInject) if (!existingPropNames.has(prop.name)) existing.push(isMultiLine ? `\n${propIndent}${prop.name}: ${prop.value},` : `, ${prop.name}: ${prop.value}`);
1238
+ if (existing.length > 0) insertionsByPos.set(insertPos, existing);
1239
+ }
1240
+ }
1241
+ ts.forEachChild(node, visit);
1242
+ };
1243
+ visit(sourceFile);
1244
+ const edits = [];
1245
+ for (const match of matches) {
1246
+ const node = match.node;
1247
+ const start = node.getFullStart();
1248
+ const end = node.getEnd();
1249
+ let removeEnd = end;
1250
+ const trailingComma = fullText.slice(end).match(/^\s*,/);
1251
+ if (trailingComma) removeEnd = end + trailingComma[0].length;
1252
+ edits.push({
1253
+ start,
1254
+ end: removeEnd,
1255
+ replacement: ""
1256
+ });
1257
+ }
1258
+ for (const [pos, insertions] of insertionsByPos) edits.push({
1259
+ start: pos,
1260
+ end: pos,
1261
+ replacement: insertions.join("")
1262
+ });
1263
+ edits.sort((a, b) => b.start - a.start);
1264
+ let text = fullText;
1265
+ for (const edit of edits) text = text.slice(0, edit.start) + edit.replacement + text.slice(edit.end);
1266
+ return text;
1267
+ }
1268
+ };
1269
+ //#endregion
1270
+ //#region src/migrations/rules/light-dom-patches.ts
1271
+ /**
1272
+ * Migration rule for slot-fix extras → `lightDomPatches`.
1273
+ *
1274
+ * In v5, the individual slot-fix flags and `experimentalSlotFixes` umbrella are replaced
1275
+ * by a single `lightDomPatches` option which defaults to `true`.
1276
+ *
1277
+ * Migration mapping:
1278
+ * - `experimentalSlotFixes: true` → remove (new default is `true`)
1279
+ * - `experimentalSlotFixes: false` → `lightDomPatches: false`
1280
+ * - Individual flags only → `lightDomPatches: { <new names> }`
1281
+ *
1282
+ * Old → new individual key names:
1283
+ * appendChildSlotFix → domMutations
1284
+ * cloneNodeFix → cloneNode
1285
+ * scopedSlotTextContentFix → textContent
1286
+ * slotChildNodesFix → childNodes
1287
+ */
1288
+ const lightDomPatchesRule = {
1289
+ id: "light-dom-patches",
1290
+ name: "Light DOM Patches Migration",
1291
+ description: "Migrate experimentalSlotFixes / individual slot-fix flags to lightDomPatches",
1292
+ fromVersion: "4.x",
1293
+ toVersion: "5.x",
1294
+ detect(sourceFile) {
1295
+ const matches = [];
1296
+ const oldKeys = new Set([
1297
+ "experimentalSlotFixes",
1298
+ "appendChildSlotFix",
1299
+ "cloneNodeFix",
1300
+ "scopedSlotTextContentFix",
1301
+ "slotChildNodesFix"
1302
+ ]);
1303
+ const visit = (node) => {
1304
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && oldKeys.has(node.name.text)) {
1305
+ const parent = node.parent;
1306
+ if (ts.isObjectLiteralExpression(parent)) {
1307
+ const grandparent = parent.parent;
1308
+ if (ts.isPropertyAssignment(grandparent) && ts.isIdentifier(grandparent.name) && grandparent.name.text === "extras") {
1309
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
1310
+ matches.push({
1311
+ node,
1312
+ message: `extras.${node.name.text} is removed. Use 'extras.lightDomPatches' instead.`,
1313
+ line: line + 1,
1314
+ column: character + 1
1315
+ });
1316
+ }
1317
+ }
1318
+ }
1319
+ ts.forEachChild(node, visit);
1320
+ };
1321
+ visit(sourceFile);
1322
+ return matches;
1323
+ },
1324
+ transform(sourceFile, matches) {
1325
+ if (matches.length === 0) return sourceFile.getFullText();
1326
+ const oldKeyMap = {};
1327
+ for (const match of matches) {
1328
+ const node = match.node;
1329
+ const key = node.name.text;
1330
+ const init = node.initializer;
1331
+ oldKeyMap[key] = init.kind === ts.SyntaxKind.TrueKeyword ? true : init.kind === ts.SyntaxKind.FalseKeyword ? false : void 0;
1332
+ }
1333
+ const keyRename = {
1334
+ appendChildSlotFix: "domMutations",
1335
+ cloneNodeFix: "cloneNode",
1336
+ scopedSlotTextContentFix: "textContent",
1337
+ slotChildNodesFix: "childNodes"
1338
+ };
1339
+ const experimentalValue = oldKeyMap["experimentalSlotFixes"];
1340
+ const hasIndividualKeys = matches.some((m) => {
1341
+ return m.node.name.text !== "experimentalSlotFixes";
1342
+ });
1343
+ let replacement = null;
1344
+ if (experimentalValue === true && !hasIndividualKeys) replacement = null;
1345
+ else if (experimentalValue === false && !hasIndividualKeys) replacement = "lightDomPatches: false";
1346
+ else if (experimentalValue === true && hasIndividualKeys) replacement = null;
1347
+ else {
1348
+ const parts = [];
1349
+ for (const [oldKey, newKey] of Object.entries(keyRename)) {
1350
+ const val = oldKeyMap[oldKey];
1351
+ if (val === true) parts.push(`${newKey}: true`);
1352
+ else if (val === false) parts.push(`${newKey}: false`);
1353
+ }
1354
+ if (parts.length > 0) replacement = `lightDomPatches: { ${parts.join(", ")} }`;
1355
+ }
1356
+ const sorted = [...matches].sort((a, b) => b.node.getStart() - a.node.getStart());
1357
+ let text = sourceFile.getFullText();
1358
+ let replacementInserted = false;
1359
+ for (const match of sorted) {
1360
+ const node = match.node;
1361
+ let start = node.getStart();
1362
+ let end = node.getEnd();
1363
+ const trailingComma = text.slice(end).match(/^(\s*,)/);
1364
+ if (trailingComma) end += trailingComma[1].length;
1365
+ else {
1366
+ const leadingComma = text.slice(0, start).match(/,\s*$/);
1367
+ if (leadingComma) start -= leadingComma[0].length;
1368
+ }
1369
+ if (!replacementInserted && replacement !== null) {
1370
+ text = text.slice(0, start) + replacement + text.slice(end);
1371
+ replacementInserted = true;
1372
+ } else text = text.slice(0, start) + text.slice(end);
1373
+ }
1374
+ text = cleanupEmptyExtras(text);
1375
+ return text;
1376
+ }
1377
+ };
1378
+ function cleanupEmptyExtras(text) {
1379
+ return text.replace(/,?\s*extras\s*:\s*\{\s*\},?/g, "");
1380
+ }
1381
+ //#endregion
1118
1382
  //#region src/migrations/rules/output-target-renames.ts
1119
1383
  /**
1120
1384
  * Migration rule for output target renames in Stencil v5.
@@ -1123,9 +1387,9 @@ function addGlobalStyleOutputTarget(text, sourceFile, injectValue) {
1123
1387
  * - Renames `dist` → `loader-bundle`
1124
1388
  * - Renames `dist-custom-elements` → `standalone`
1125
1389
  * - Renames `dist-hydrate-script` → `ssr`
1126
- * - Renames `dist-collection` → `stencil-rebundle`
1390
+ * - Renames `dist-collection` → `collection`
1127
1391
  * - Renames `dist-types` → `types`
1128
- * - Extracts `collectionDir` from loader-bundle into separate `stencil-rebundle` output
1392
+ * - Extracts `collectionDir` from loader-bundle into separate `collection` output
1129
1393
  * - Extracts `typesDir` from loader-bundle into separate `types` output
1130
1394
  * - Renames `esmLoaderPath` → `loaderPath` (applies to all module formats, not just ESM)
1131
1395
  * - Removes `isPrimaryPackageOutputTarget` (no longer needed, package.json validation auto-detects)
@@ -1143,7 +1407,7 @@ const outputTargetRenamesRule = {
1143
1407
  dist: "loader-bundle",
1144
1408
  "dist-custom-elements": "standalone",
1145
1409
  "dist-hydrate-script": "ssr",
1146
- "dist-collection": "stencil-rebundle",
1410
+ "dist-collection": "collection",
1147
1411
  "dist-types": "types"
1148
1412
  };
1149
1413
  const visit = (node) => {
@@ -1165,7 +1429,7 @@ const outputTargetRenamesRule = {
1165
1429
  if (parent.properties.some((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "type")) {
1166
1430
  const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
1167
1431
  const propName = node.name.text;
1168
- const newType = propName === "collectionDir" ? "stencil-rebundle" : "types";
1432
+ const newType = propName === "collectionDir" ? "collection" : "types";
1169
1433
  matches.push({
1170
1434
  node,
1171
1435
  message: `Property '${propName}' will be extracted to separate '${newType}' output target`,
@@ -1217,7 +1481,7 @@ const outputTargetRenamesRule = {
1217
1481
  dist: "loader-bundle",
1218
1482
  "dist-custom-elements": "standalone",
1219
1483
  "dist-hydrate-script": "ssr",
1220
- "dist-collection": "stencil-rebundle",
1484
+ "dist-collection": "collection",
1221
1485
  "dist-types": "types"
1222
1486
  };
1223
1487
  const outputTargetsToExtract = [];
@@ -1335,7 +1599,7 @@ function addExtractedOutputTargets(text, sourceFile, toExtract) {
1335
1599
  if (afterLastElement && afterLastElement[1]) insertPos += afterLastElement[0].length;
1336
1600
  const newTargets = [];
1337
1601
  for (const extracted of toExtract) {
1338
- if (extracted.collectionDir) newTargets.push(`{\n${indent} type: 'stencil-rebundle',\n${indent} dir: '${extracted.collectionDir}',\n${indent}}`);
1602
+ if (extracted.collectionDir) newTargets.push(`{\n${indent} type: 'collection',\n${indent} dir: '${extracted.collectionDir}',\n${indent}}`);
1339
1603
  if (extracted.typesDir) newTargets.push(`{\n${indent} type: 'types',\n${indent} dir: '${extracted.typesDir}',\n${indent}}`);
1340
1604
  }
1341
1605
  if (newTargets.length === 0) return text;
@@ -1344,6 +1608,167 @@ function addExtractedOutputTargets(text, sourceFile, toExtract) {
1344
1608
  return text;
1345
1609
  }
1346
1610
  //#endregion
1611
+ //#region src/migrations/rules/rolldown-config.ts
1612
+ /**
1613
+ * NodeResolve fields that were valid in @rollup/plugin-node-resolve but don't exist
1614
+ * in rolldown's native resolver and should be removed.
1615
+ */
1616
+ const REMOVED_NODE_RESOLVE_FIELDS = new Set([
1617
+ "browser",
1618
+ "modulePaths",
1619
+ "dedupe",
1620
+ "jail",
1621
+ "modulesOnly",
1622
+ "preferBuiltins",
1623
+ "resolveOnly",
1624
+ "rootDir",
1625
+ "allowExportsFolderMapping"
1626
+ ]);
1627
+ /** Fields renamed between @rollup/plugin-node-resolve and rolldown's native resolver. */
1628
+ const RENAMED_NODE_RESOLVE_FIELDS = {
1629
+ exportConditions: "conditionNames",
1630
+ moduleDirectories: "modules"
1631
+ };
1632
+ function isInsideNodeResolve(node) {
1633
+ const parent = node.parent;
1634
+ if (!ts.isObjectLiteralExpression(parent)) return false;
1635
+ const grandParent = parent.parent;
1636
+ return ts.isPropertyAssignment(grandParent) && ts.isIdentifier(grandParent.name) && grandParent.name.text === "nodeResolve";
1637
+ }
1638
+ /**
1639
+ * Migration rule for rolldown-related config changes in Stencil v5.
1640
+ *
1641
+ * Handles:
1642
+ * - `rollupConfig` → `rolldownConfig` (key rename + flatten `inputOptions`)
1643
+ * - `rolldownConfig: { inputOptions: { ... } }` → `rolldownConfig: { ... }` (flatten)
1644
+ * - `rollupPlugins` → `rolldownPlugins`
1645
+ * - `nodeResolve.exportConditions` → `nodeResolve.conditionNames`
1646
+ * - `nodeResolve.moduleDirectories` → `nodeResolve.modules`
1647
+ * - Removes unsupported `nodeResolve` fields (`browser`, `dedupe`, `jail`, etc.)
1648
+ */
1649
+ const rolldownConfigRule = {
1650
+ id: "rolldown-config",
1651
+ name: "Rolldown Config Migration",
1652
+ description: "Migrate rollup/rolldown config options to v5 rolldown-native API",
1653
+ fromVersion: "4.x",
1654
+ toVersion: "5.x",
1655
+ detect(sourceFile) {
1656
+ const matches = [];
1657
+ const visit = (node) => {
1658
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
1659
+ const name = node.name.text;
1660
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
1661
+ if (name === "rollupPlugins") matches.push({
1662
+ node,
1663
+ message: `'rollupPlugins' renamed to 'rolldownPlugins'`,
1664
+ line: line + 1,
1665
+ column: character + 1
1666
+ });
1667
+ else if (name === "rollupConfig" || name === "rolldownConfig") {
1668
+ const value = node.initializer;
1669
+ if (name === "rollupConfig" || ts.isObjectLiteralExpression(value) && value.properties.some((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "inputOptions")) matches.push({
1670
+ node,
1671
+ message: name === "rollupConfig" ? `'rollupConfig' renamed to 'rolldownConfig'; 'inputOptions' wrapper removed` : `'rolldownConfig.inputOptions' wrapper removed - options are now top-level`,
1672
+ line: line + 1,
1673
+ column: character + 1
1674
+ });
1675
+ } else if (name in RENAMED_NODE_RESOLVE_FIELDS && isInsideNodeResolve(node)) matches.push({
1676
+ node,
1677
+ message: `'nodeResolve.${name}' renamed to 'nodeResolve.${RENAMED_NODE_RESOLVE_FIELDS[name]}'`,
1678
+ line: line + 1,
1679
+ column: character + 1
1680
+ });
1681
+ else if (REMOVED_NODE_RESOLVE_FIELDS.has(name) && isInsideNodeResolve(node)) matches.push({
1682
+ node,
1683
+ message: `'nodeResolve.${name}' is not supported by rolldown's native resolver and will be removed`,
1684
+ line: line + 1,
1685
+ column: character + 1
1686
+ });
1687
+ }
1688
+ ts.forEachChild(node, visit);
1689
+ };
1690
+ visit(sourceFile);
1691
+ return matches;
1692
+ },
1693
+ transform(sourceFile, matches) {
1694
+ if (matches.length === 0) return sourceFile.getFullText();
1695
+ const edits = [];
1696
+ const fullText = sourceFile.getFullText();
1697
+ for (const match of matches) {
1698
+ const node = match.node;
1699
+ const name = node.name.text;
1700
+ if (name === "rollupPlugins") {
1701
+ const nameStart = node.name.getStart(sourceFile);
1702
+ const nameEnd = node.name.getEnd();
1703
+ edits.push({
1704
+ start: nameStart,
1705
+ end: nameEnd,
1706
+ replacement: "rolldownPlugins"
1707
+ });
1708
+ continue;
1709
+ }
1710
+ if (name in RENAMED_NODE_RESOLVE_FIELDS && isInsideNodeResolve(node)) {
1711
+ const nameStart = node.name.getStart(sourceFile);
1712
+ const nameEnd = node.name.getEnd();
1713
+ edits.push({
1714
+ start: nameStart,
1715
+ end: nameEnd,
1716
+ replacement: RENAMED_NODE_RESOLVE_FIELDS[name]
1717
+ });
1718
+ continue;
1719
+ }
1720
+ if (REMOVED_NODE_RESOLVE_FIELDS.has(name) && isInsideNodeResolve(node)) {
1721
+ const start = node.getFullStart();
1722
+ const end = node.getEnd();
1723
+ const trailingComma = fullText.slice(end).match(/^\s*,/);
1724
+ edits.push({
1725
+ start,
1726
+ end: trailingComma ? end + trailingComma[0].length : end,
1727
+ replacement: ""
1728
+ });
1729
+ continue;
1730
+ }
1731
+ if (name === "rollupConfig" || name === "rolldownConfig") {
1732
+ const value = node.initializer;
1733
+ if (!ts.isObjectLiteralExpression(value)) {
1734
+ if (name === "rollupConfig") {
1735
+ const nameStart = node.name.getStart(sourceFile);
1736
+ edits.push({
1737
+ start: nameStart,
1738
+ end: node.name.getEnd(),
1739
+ replacement: "rolldownConfig"
1740
+ });
1741
+ }
1742
+ continue;
1743
+ }
1744
+ const inputOptionsProp = value.properties.find((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "inputOptions");
1745
+ if (!inputOptionsProp) {
1746
+ if (name === "rollupConfig") {
1747
+ const nameStart = node.name.getStart(sourceFile);
1748
+ edits.push({
1749
+ start: nameStart,
1750
+ end: node.name.getEnd(),
1751
+ replacement: "rolldownConfig"
1752
+ });
1753
+ }
1754
+ continue;
1755
+ }
1756
+ const newValueText = inputOptionsProp.initializer.getText(sourceFile);
1757
+ const keyStart = node.name.getStart(sourceFile);
1758
+ edits.push({
1759
+ start: keyStart,
1760
+ end: node.getEnd(),
1761
+ replacement: `rolldownConfig: ${newValueText}`
1762
+ });
1763
+ }
1764
+ }
1765
+ edits.sort((a, b) => b.start - a.start);
1766
+ let text = fullText;
1767
+ for (const edit of edits) text = text.slice(0, edit.start) + edit.replacement + text.slice(edit.end);
1768
+ return text;
1769
+ }
1770
+ };
1771
+ //#endregion
1347
1772
  //#region src/migrations/index.ts
1348
1773
  /**
1349
1774
  * Build a map of local import names to their original names from @stencil/core.
@@ -1387,7 +1812,11 @@ const migrationRules = [
1387
1812
  buildDistDocsRule,
1388
1813
  outputTargetRenamesRule,
1389
1814
  devModeRule,
1390
- globalStyleInjectRule
1815
+ globalStyleInjectRule,
1816
+ lightDomPatchesRule,
1817
+ externalRuntimeRule,
1818
+ hashFileNamesRule,
1819
+ rolldownConfigRule
1391
1820
  ];
1392
1821
  /**
1393
1822
  * Get all migration rules for a specific version upgrade.
@@ -1576,6 +2005,23 @@ async function getTypeScriptFiles(config, sys, logger) {
1576
2005
  const configFile = config.configPath;
1577
2006
  if (configFile && (configFile.endsWith(".ts") || configFile.endsWith(".mts"))) {
1578
2007
  if (!files.includes(configFile)) files.push(configFile);
2008
+ const configContent = await sys.readFile(configFile);
2009
+ if (configContent) {
2010
+ const configSourceFile = ts.createSourceFile(configFile, configContent, ts.ScriptTarget.Latest, true);
2011
+ const configDir = dirname(configFile);
2012
+ for (const statement of configSourceFile.statements) if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
2013
+ const specifier = statement.moduleSpecifier.text;
2014
+ if (!specifier.startsWith("./") && !specifier.startsWith("../")) continue;
2015
+ const basePath = join(configDir, specifier);
2016
+ const candidates = basePath.endsWith(".ts") || basePath.endsWith(".tsx") ? [basePath] : [`${basePath}.ts`, `${basePath}.tsx`];
2017
+ for (const candidate of candidates) if (!candidate.endsWith(".d.ts") && !files.includes(candidate) && candidate.startsWith(config.rootDir)) {
2018
+ if (await sys.readFile(candidate)) {
2019
+ files.push(candidate);
2020
+ break;
2021
+ }
2022
+ }
2023
+ }
2024
+ }
1579
2025
  }
1580
2026
  return files;
1581
2027
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/cli",
3
- "version": "5.0.0-alpha.5",
3
+ "version": "5.0.0-alpha.6",
4
4
  "description": "CLI for Stencil - Web component compiler",
5
5
  "keywords": [
6
6
  "components",
@@ -37,15 +37,15 @@
37
37
  "./cli": "./bin/stencil.mjs"
38
38
  },
39
39
  "dependencies": {
40
- "prompts": "^2.4.2",
41
- "@stencil/dev-server": "5.0.0-alpha.5"
40
+ "prompts": "^2.0.0",
41
+ "@stencil/dev-server": "5.0.0-alpha.6"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/prompts": "^2.4.9",
45
- "tsdown": "^0.21.7",
46
- "typescript": ">4.0.0",
47
- "vitest": "^4.1.1",
48
- "@stencil/core": "5.0.0-alpha.5"
45
+ "tsdown": ">=0.21.0 <1.0.0",
46
+ "typescript": ">4.0.0 <7.0.0",
47
+ "vitest": "^4.1.7",
48
+ "@stencil/core": "5.0.0-alpha.6"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@stencil/core": "^5.0.0-0"