@stencil/cli 5.0.0-alpha.2 → 5.0.0-alpha.3
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 +8 -8
- package/dist/index.mjs +525 -133
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -5,33 +5,33 @@ import { LogLevel } from "@stencil/core/compiler";
|
|
|
5
5
|
/**
|
|
6
6
|
* Supported CLI task commands
|
|
7
7
|
*/
|
|
8
|
-
type TaskCommand = 'build' | 'docs' | 'generate' | 'g' | 'help' | 'info' | 'prerender' | 'serve' | 'telemetry' | 'test' | 'version';
|
|
8
|
+
type TaskCommand = 'build' | 'docs' | 'generate' | 'g' | 'help' | 'info' | 'migrate' | 'prerender' | 'serve' | 'telemetry' | 'test' | 'version';
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/config-flags.d.ts
|
|
11
11
|
/**
|
|
12
12
|
* All the Boolean options supported by the Stencil CLI
|
|
13
13
|
*/
|
|
14
|
-
declare const BOOLEAN_CLI_FLAGS: readonly ["build", "cache", "checkVersion", "ci", "compare", "debug", "dev", "devtools", "docs", "
|
|
14
|
+
declare const BOOLEAN_CLI_FLAGS: readonly ["build", "cache", "checkVersion", "ci", "compare", "debug", "dev", "devtools", "docs", "dryRun", "esm", "help", "log", "open", "prerender", "prerenderExternal", "prod", "profile", "serviceWorker", "serve", "skipNodeCheck", "ssr", "verbose", "version", "watch"];
|
|
15
15
|
/**
|
|
16
16
|
* All the Number options supported by the Stencil CLI
|
|
17
17
|
*/
|
|
18
|
-
declare const NUMBER_CLI_FLAGS: readonly ["port"
|
|
18
|
+
declare const NUMBER_CLI_FLAGS: readonly ["port"];
|
|
19
19
|
/**
|
|
20
20
|
* All the String options supported by the Stencil CLI
|
|
21
21
|
*/
|
|
22
|
-
declare const STRING_CLI_FLAGS: readonly ["address", "config", "docsApi", "docsJson", "emulate", "root"
|
|
23
|
-
declare const STRING_ARRAY_CLI_FLAGS: readonly [
|
|
22
|
+
declare const STRING_CLI_FLAGS: readonly ["address", "config", "docsApi", "docsJson", "emulate", "root"];
|
|
23
|
+
declare const STRING_ARRAY_CLI_FLAGS: readonly [];
|
|
24
24
|
/**
|
|
25
25
|
* All the CLI arguments which may have string or number values
|
|
26
26
|
*
|
|
27
|
-
* `maxWorkers`
|
|
28
|
-
*
|
|
27
|
+
* `maxWorkers` controls the number of concurrent workers for Stencil builds.
|
|
28
|
+
* Supports both string (e.g., "50%") and number values.
|
|
29
29
|
*/
|
|
30
30
|
declare const STRING_NUMBER_CLI_FLAGS: readonly ["maxWorkers"];
|
|
31
31
|
/**
|
|
32
32
|
* All the CLI arguments which may have boolean or string values.
|
|
33
33
|
*/
|
|
34
|
-
declare const BOOLEAN_STRING_CLI_FLAGS: readonly ["
|
|
34
|
+
declare const BOOLEAN_STRING_CLI_FLAGS: readonly ["stats"];
|
|
35
35
|
/**
|
|
36
36
|
* All the LogLevel-type options supported by the Stencil CLI
|
|
37
37
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LOG_LEVELS } from "@stencil/core/compiler";
|
|
2
2
|
import { buildError, catchError, hasError, isFunction, isOutputTargetDocs, isOutputTargetHydrate, isOutputTargetWww, isString, normalizePath, readOnlyArrayHasStringMember, result, shouldIgnoreError, toCamelCase, validateComponentTag } from "@stencil/core/compiler/utils";
|
|
3
|
-
import { join, parse, relative } from "path";
|
|
3
|
+
import { isAbsolute, join, parse, relative } from "path";
|
|
4
|
+
import ts from "typescript";
|
|
4
5
|
import { start } from "@stencil/dev-server";
|
|
5
6
|
//#region src/config-flags.ts
|
|
6
7
|
/**
|
|
@@ -16,8 +17,7 @@ const BOOLEAN_CLI_FLAGS = [
|
|
|
16
17
|
"dev",
|
|
17
18
|
"devtools",
|
|
18
19
|
"docs",
|
|
19
|
-
"
|
|
20
|
-
"es5",
|
|
20
|
+
"dryRun",
|
|
21
21
|
"esm",
|
|
22
22
|
"help",
|
|
23
23
|
"log",
|
|
@@ -27,64 +27,17 @@ const BOOLEAN_CLI_FLAGS = [
|
|
|
27
27
|
"prod",
|
|
28
28
|
"profile",
|
|
29
29
|
"serviceWorker",
|
|
30
|
-
"screenshot",
|
|
31
30
|
"serve",
|
|
32
31
|
"skipNodeCheck",
|
|
33
|
-
"spec",
|
|
34
32
|
"ssr",
|
|
35
|
-
"updateScreenshot",
|
|
36
33
|
"verbose",
|
|
37
34
|
"version",
|
|
38
|
-
"watch"
|
|
39
|
-
"all",
|
|
40
|
-
"automock",
|
|
41
|
-
"bail",
|
|
42
|
-
"changedFilesWithAncestor",
|
|
43
|
-
"clearCache",
|
|
44
|
-
"clearMocks",
|
|
45
|
-
"collectCoverage",
|
|
46
|
-
"color",
|
|
47
|
-
"colors",
|
|
48
|
-
"coverage",
|
|
49
|
-
"detectLeaks",
|
|
50
|
-
"detectOpenHandles",
|
|
51
|
-
"errorOnDeprecated",
|
|
52
|
-
"expand",
|
|
53
|
-
"findRelatedTests",
|
|
54
|
-
"forceExit",
|
|
55
|
-
"init",
|
|
56
|
-
"injectGlobals",
|
|
57
|
-
"json",
|
|
58
|
-
"lastCommit",
|
|
59
|
-
"listTests",
|
|
60
|
-
"logHeapUsage",
|
|
61
|
-
"noStackTrace",
|
|
62
|
-
"notify",
|
|
63
|
-
"onlyChanged",
|
|
64
|
-
"onlyFailures",
|
|
65
|
-
"passWithNoTests",
|
|
66
|
-
"resetMocks",
|
|
67
|
-
"resetModules",
|
|
68
|
-
"restoreMocks",
|
|
69
|
-
"runInBand",
|
|
70
|
-
"runTestsByPath",
|
|
71
|
-
"showConfig",
|
|
72
|
-
"silent",
|
|
73
|
-
"skipFilter",
|
|
74
|
-
"testLocationInResults",
|
|
75
|
-
"updateSnapshot",
|
|
76
|
-
"useStderr",
|
|
77
|
-
"watchAll",
|
|
78
|
-
"watchman"
|
|
35
|
+
"watch"
|
|
79
36
|
];
|
|
80
37
|
/**
|
|
81
38
|
* All the Number options supported by the Stencil CLI
|
|
82
39
|
*/
|
|
83
|
-
const NUMBER_CLI_FLAGS = [
|
|
84
|
-
"port",
|
|
85
|
-
"maxConcurrency",
|
|
86
|
-
"testTimeout"
|
|
87
|
-
];
|
|
40
|
+
const NUMBER_CLI_FLAGS = ["port"];
|
|
88
41
|
/**
|
|
89
42
|
* All the String options supported by the Stencil CLI
|
|
90
43
|
*/
|
|
@@ -94,72 +47,20 @@ const STRING_CLI_FLAGS = [
|
|
|
94
47
|
"docsApi",
|
|
95
48
|
"docsJson",
|
|
96
49
|
"emulate",
|
|
97
|
-
"root"
|
|
98
|
-
"screenshotConnector",
|
|
99
|
-
"cacheDirectory",
|
|
100
|
-
"changedSince",
|
|
101
|
-
"collectCoverageFrom",
|
|
102
|
-
"coverageDirectory",
|
|
103
|
-
"coverageThreshold",
|
|
104
|
-
"env",
|
|
105
|
-
"filter",
|
|
106
|
-
"globalSetup",
|
|
107
|
-
"globalTeardown",
|
|
108
|
-
"globals",
|
|
109
|
-
"haste",
|
|
110
|
-
"moduleNameMapper",
|
|
111
|
-
"notifyMode",
|
|
112
|
-
"outputFile",
|
|
113
|
-
"preset",
|
|
114
|
-
"prettierPath",
|
|
115
|
-
"resolver",
|
|
116
|
-
"rootDir",
|
|
117
|
-
"runner",
|
|
118
|
-
"testEnvironment",
|
|
119
|
-
"testEnvironmentOptions",
|
|
120
|
-
"testFailureExitCode",
|
|
121
|
-
"testNamePattern",
|
|
122
|
-
"testResultsProcessor",
|
|
123
|
-
"testRunner",
|
|
124
|
-
"testSequencer",
|
|
125
|
-
"testURL",
|
|
126
|
-
"timers",
|
|
127
|
-
"transform"
|
|
128
|
-
];
|
|
129
|
-
const STRING_ARRAY_CLI_FLAGS = [
|
|
130
|
-
"collectCoverageOnlyFrom",
|
|
131
|
-
"coveragePathIgnorePatterns",
|
|
132
|
-
"coverageReporters",
|
|
133
|
-
"moduleDirectories",
|
|
134
|
-
"moduleFileExtensions",
|
|
135
|
-
"modulePathIgnorePatterns",
|
|
136
|
-
"modulePaths",
|
|
137
|
-
"projects",
|
|
138
|
-
"reporters",
|
|
139
|
-
"roots",
|
|
140
|
-
"selectProjects",
|
|
141
|
-
"setupFiles",
|
|
142
|
-
"setupFilesAfterEnv",
|
|
143
|
-
"snapshotSerializers",
|
|
144
|
-
"testMatch",
|
|
145
|
-
"testPathIgnorePatterns",
|
|
146
|
-
"testPathPattern",
|
|
147
|
-
"testRegex",
|
|
148
|
-
"transformIgnorePatterns",
|
|
149
|
-
"unmockedModulePathPatterns",
|
|
150
|
-
"watchPathIgnorePatterns"
|
|
50
|
+
"root"
|
|
151
51
|
];
|
|
52
|
+
const STRING_ARRAY_CLI_FLAGS = [];
|
|
152
53
|
/**
|
|
153
54
|
* All the CLI arguments which may have string or number values
|
|
154
55
|
*
|
|
155
|
-
* `maxWorkers`
|
|
156
|
-
*
|
|
56
|
+
* `maxWorkers` controls the number of concurrent workers for Stencil builds.
|
|
57
|
+
* Supports both string (e.g., "50%") and number values.
|
|
157
58
|
*/
|
|
158
59
|
const STRING_NUMBER_CLI_FLAGS = ["maxWorkers"];
|
|
159
60
|
/**
|
|
160
61
|
* All the CLI arguments which may have boolean or string values.
|
|
161
62
|
*/
|
|
162
|
-
const BOOLEAN_STRING_CLI_FLAGS = ["
|
|
63
|
+
const BOOLEAN_STRING_CLI_FLAGS = ["stats"];
|
|
163
64
|
/**
|
|
164
65
|
* All the LogLevel-type options supported by the Stencil CLI
|
|
165
66
|
*
|
|
@@ -175,21 +76,13 @@ const CLI_FLAG_ALIASES = {
|
|
|
175
76
|
c: "config",
|
|
176
77
|
h: "help",
|
|
177
78
|
p: "port",
|
|
178
|
-
v: "version"
|
|
179
|
-
b: "bail",
|
|
180
|
-
e: "expand",
|
|
181
|
-
f: "onlyFailures",
|
|
182
|
-
i: "runInBand",
|
|
183
|
-
o: "onlyChanged",
|
|
184
|
-
t: "testNamePattern",
|
|
185
|
-
u: "updateSnapshot",
|
|
186
|
-
w: "maxWorkers"
|
|
79
|
+
v: "version"
|
|
187
80
|
};
|
|
188
81
|
/**
|
|
189
82
|
* A regular expression which can be used to match a CLI flag for one of our
|
|
190
83
|
* short aliases.
|
|
191
84
|
*/
|
|
192
|
-
const CLI_FLAG_REGEX = new RegExp(`^-[
|
|
85
|
+
const CLI_FLAG_REGEX = new RegExp(`^-[chpv]{1}$`);
|
|
193
86
|
/**
|
|
194
87
|
* Helper function for initializing a `ConfigFlags` object. Provide any overrides
|
|
195
88
|
* for default values and off you go!
|
|
@@ -354,9 +247,10 @@ const setCLIArg = (flags, rawArg, normalizedArg, value) => {
|
|
|
354
247
|
flags.knownArgs.push(rawArg);
|
|
355
248
|
flags.knownArgs.push(value);
|
|
356
249
|
} else throwCLIParsingError(rawArg, "expected a string argument but received nothing");
|
|
357
|
-
else if (readOnlyArrayHasStringMember(STRING_ARRAY_CLI_FLAGS, normalizedArg)) if (typeof value === "string") {
|
|
358
|
-
|
|
359
|
-
|
|
250
|
+
else if (STRING_ARRAY_CLI_FLAGS.length > 0 && readOnlyArrayHasStringMember(STRING_ARRAY_CLI_FLAGS, normalizedArg)) if (typeof value === "string") {
|
|
251
|
+
const flagsRecord = flags;
|
|
252
|
+
if (!Array.isArray(flagsRecord[normalizedArg])) flagsRecord[normalizedArg] = [];
|
|
253
|
+
const targetArray = flagsRecord[normalizedArg];
|
|
360
254
|
if (Array.isArray(targetArray)) {
|
|
361
255
|
targetArray.push(value);
|
|
362
256
|
flags.knownArgs.push(rawArg);
|
|
@@ -657,7 +551,6 @@ const startupCompilerLog = (coreCompiler, config) => {
|
|
|
657
551
|
const isDevBuild = coreCompiler.version.includes("-dev.");
|
|
658
552
|
if (isPrerelease && !isDevBuild) logger.warn(logger.yellow(`This is a prerelease build, undocumented changes might happen at any time. Technical support is not available for prereleases, but any assistance testing is appreciated.`));
|
|
659
553
|
if (config.devMode && !isDebug) {
|
|
660
|
-
if (config.buildEs5) logger.warn(`Generating ES5 during development is a very task expensive, initial and incremental builds will be much slower. Drop the '--es5' flag and use a modern browser for development.`);
|
|
661
554
|
if (!config.enableCache) logger.warn(`Disabling cache during development will slow down incremental builds.`);
|
|
662
555
|
}
|
|
663
556
|
};
|
|
@@ -692,7 +585,6 @@ const mergeFlags = (config, flags) => {
|
|
|
692
585
|
if (typeof flags.docsJson === "string") merged.docsJsonPath = flags.docsJson;
|
|
693
586
|
if (flags.stats) merged.statsJsonPath = flags.stats;
|
|
694
587
|
if (typeof flags.serviceWorker === "boolean") merged.generateServiceWorker = flags.serviceWorker;
|
|
695
|
-
if (typeof flags.e2e === "boolean") merged.e2eTests = flags.e2e;
|
|
696
588
|
if (typeof flags.maxWorkers === "number") merged.maxConcurrentWorkers = flags.maxWorkers;
|
|
697
589
|
if (typeof flags.address === "string") merged.devServerAddress = flags.address;
|
|
698
590
|
if (typeof flags.port === "number") merged.devServerPort = flags.port;
|
|
@@ -726,6 +618,432 @@ const printCheckVersionResults = async (versionChecker) => {
|
|
|
726
618
|
}
|
|
727
619
|
};
|
|
728
620
|
//#endregion
|
|
621
|
+
//#region src/migrations/rules/encapsulation-api.ts
|
|
622
|
+
/**
|
|
623
|
+
* Migration rule for the @Component encapsulation API change.
|
|
624
|
+
*
|
|
625
|
+
* Migrates:
|
|
626
|
+
* - `shadow: true` → `encapsulation: { type: 'shadow' }`
|
|
627
|
+
* - `shadow: { delegatesFocus: true }` → `encapsulation: { type: 'shadow', delegatesFocus: true }`
|
|
628
|
+
* - `scoped: true` → `encapsulation: { type: 'scoped' }`
|
|
629
|
+
*/
|
|
630
|
+
const encapsulationApiRule = {
|
|
631
|
+
id: "encapsulation-api",
|
|
632
|
+
name: "Encapsulation API",
|
|
633
|
+
description: "Migrate shadow/scoped properties to new encapsulation API",
|
|
634
|
+
fromVersion: "4.x",
|
|
635
|
+
toVersion: "5.x",
|
|
636
|
+
detect(sourceFile) {
|
|
637
|
+
const matches = [];
|
|
638
|
+
const importMap = getStencilCoreImportMap(sourceFile);
|
|
639
|
+
const visit = (node) => {
|
|
640
|
+
if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {
|
|
641
|
+
const decoratorName = node.expression.expression;
|
|
642
|
+
if (ts.isIdentifier(decoratorName) && isStencilDecorator(decoratorName.text, "Component", importMap)) {
|
|
643
|
+
const [arg] = node.expression.arguments;
|
|
644
|
+
if (arg && ts.isObjectLiteralExpression(arg)) {
|
|
645
|
+
for (const prop of arg.properties) if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
646
|
+
const propName = prop.name.text;
|
|
647
|
+
if (propName === "shadow" || propName === "scoped") {
|
|
648
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(prop.getStart());
|
|
649
|
+
matches.push({
|
|
650
|
+
node: prop,
|
|
651
|
+
message: `Deprecated '${propName}' property found - migrate to 'encapsulation' API`,
|
|
652
|
+
line: line + 1,
|
|
653
|
+
column: character + 1
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
ts.forEachChild(node, visit);
|
|
661
|
+
};
|
|
662
|
+
visit(sourceFile);
|
|
663
|
+
return matches;
|
|
664
|
+
},
|
|
665
|
+
transform(sourceFile, matches) {
|
|
666
|
+
if (matches.length === 0) return sourceFile.getFullText();
|
|
667
|
+
let text = sourceFile.getFullText();
|
|
668
|
+
const sortedMatches = [...matches].sort((a, b) => {
|
|
669
|
+
const posA = a.node.getStart();
|
|
670
|
+
return b.node.getStart() - posA;
|
|
671
|
+
});
|
|
672
|
+
for (const match of sortedMatches) {
|
|
673
|
+
const prop = match.node;
|
|
674
|
+
const propName = prop.name.text;
|
|
675
|
+
const start = prop.getStart();
|
|
676
|
+
const end = prop.getEnd();
|
|
677
|
+
let replacement;
|
|
678
|
+
if (propName === "shadow") if (prop.initializer.kind === ts.SyntaxKind.TrueKeyword) replacement = "encapsulation: { type: 'shadow' }";
|
|
679
|
+
else if (ts.isObjectLiteralExpression(prop.initializer)) {
|
|
680
|
+
const options = [];
|
|
681
|
+
for (const innerProp of prop.initializer.properties) if (ts.isPropertyAssignment(innerProp) && ts.isIdentifier(innerProp.name)) {
|
|
682
|
+
const optName = innerProp.name.text;
|
|
683
|
+
const optValue = innerProp.initializer.getText();
|
|
684
|
+
options.push(`${optName}: ${optValue}`);
|
|
685
|
+
}
|
|
686
|
+
if (options.length > 0) replacement = `encapsulation: { type: 'shadow', ${options.join(", ")} }`;
|
|
687
|
+
else replacement = "encapsulation: { type: 'shadow' }";
|
|
688
|
+
} else replacement = "";
|
|
689
|
+
else if (propName === "scoped") if (prop.initializer.kind === ts.SyntaxKind.TrueKeyword) replacement = "encapsulation: { type: 'scoped' }";
|
|
690
|
+
else replacement = "";
|
|
691
|
+
else continue;
|
|
692
|
+
let endPos = end;
|
|
693
|
+
const afterProp = text.slice(end).match(/^\s*,/);
|
|
694
|
+
if (afterProp && replacement === "") endPos = end + afterProp[0].length;
|
|
695
|
+
else if (afterProp && replacement !== "") {} else if (!afterProp && replacement !== "") {}
|
|
696
|
+
text = text.slice(0, start) + replacement + text.slice(endPos);
|
|
697
|
+
}
|
|
698
|
+
return text;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/migrations/rules/form-associated.ts
|
|
703
|
+
/**
|
|
704
|
+
* Migration rule for formAssociated → @AttachInternals.
|
|
705
|
+
*
|
|
706
|
+
* Migrates:
|
|
707
|
+
* - `formAssociated: true` in @Component → Adds `@AttachInternals() internals: ElementInternals;`
|
|
708
|
+
*/
|
|
709
|
+
const formAssociatedRule = {
|
|
710
|
+
id: "form-associated",
|
|
711
|
+
name: "Form Associated",
|
|
712
|
+
description: "Migrate formAssociated to @AttachInternals decorator",
|
|
713
|
+
fromVersion: "4.x",
|
|
714
|
+
toVersion: "5.x",
|
|
715
|
+
detect(sourceFile) {
|
|
716
|
+
const matches = [];
|
|
717
|
+
const importMap = getStencilCoreImportMap(sourceFile);
|
|
718
|
+
let hasAttachInternalsImport = false;
|
|
719
|
+
let stencilImportEnd = 0;
|
|
720
|
+
for (const statement of sourceFile.statements) if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier) && statement.moduleSpecifier.text === "@stencil/core") {
|
|
721
|
+
stencilImportEnd = statement.getEnd();
|
|
722
|
+
for (const [, originalName] of importMap) if (originalName === "AttachInternals") {
|
|
723
|
+
hasAttachInternalsImport = true;
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
const visit = (node) => {
|
|
729
|
+
if (ts.isClassDeclaration(node)) {
|
|
730
|
+
const decorators = ts.getDecorators(node);
|
|
731
|
+
if (!decorators) {
|
|
732
|
+
ts.forEachChild(node, visit);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
let componentDecorator;
|
|
736
|
+
let formAssociatedProp;
|
|
737
|
+
for (const decorator of decorators) if (ts.isCallExpression(decorator.expression) && ts.isIdentifier(decorator.expression.expression) && isStencilDecorator(decorator.expression.expression.text, "Component", importMap)) {
|
|
738
|
+
componentDecorator = decorator;
|
|
739
|
+
const [arg] = decorator.expression.arguments;
|
|
740
|
+
if (arg && ts.isObjectLiteralExpression(arg)) {
|
|
741
|
+
for (const prop of arg.properties) if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === "formAssociated") {
|
|
742
|
+
formAssociatedProp = prop;
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
if (componentDecorator && formAssociatedProp) {
|
|
749
|
+
let hasAttachInternals = false;
|
|
750
|
+
for (const member of node.members) if (ts.isPropertyDeclaration(member) || ts.isMethodDeclaration(member)) {
|
|
751
|
+
const memberDecorators = ts.getDecorators(member);
|
|
752
|
+
if (memberDecorators) {
|
|
753
|
+
for (const d of memberDecorators) if (ts.isCallExpression(d.expression) && ts.isIdentifier(d.expression.expression) && isStencilDecorator(d.expression.expression.text, "AttachInternals", importMap)) {
|
|
754
|
+
hasAttachInternals = true;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
let searchStart = node.name ? node.name.getEnd() : node.getStart(sourceFile);
|
|
760
|
+
if (node.heritageClauses) for (const clause of node.heritageClauses) searchStart = Math.max(searchStart, clause.getEnd());
|
|
761
|
+
const braceMatch = sourceFile.getFullText().slice(searchStart).match(/\s*\{/);
|
|
762
|
+
if (!braceMatch) {
|
|
763
|
+
ts.forEachChild(node, visit);
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
const classBodyStart = searchStart + braceMatch[0].length;
|
|
767
|
+
let indent = " ";
|
|
768
|
+
if (node.members.length > 0) {
|
|
769
|
+
const memberStart = node.members[0].getStart(sourceFile);
|
|
770
|
+
const indentMatch = sourceFile.getFullText().slice(classBodyStart, memberStart).match(/\n(\s+)/);
|
|
771
|
+
if (indentMatch) indent = indentMatch[1];
|
|
772
|
+
}
|
|
773
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(formAssociatedProp.getStart());
|
|
774
|
+
matches.push({
|
|
775
|
+
node: formAssociatedProp,
|
|
776
|
+
message: hasAttachInternals ? "Remove 'formAssociated' (already has @AttachInternals)" : "Migrate 'formAssociated' to @AttachInternals decorator",
|
|
777
|
+
line: line + 1,
|
|
778
|
+
column: character + 1,
|
|
779
|
+
classBodyStart,
|
|
780
|
+
hasAttachInternals,
|
|
781
|
+
indent,
|
|
782
|
+
needsImport: !hasAttachInternalsImport && !hasAttachInternals,
|
|
783
|
+
stencilImportEnd
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
ts.forEachChild(node, visit);
|
|
788
|
+
};
|
|
789
|
+
visit(sourceFile);
|
|
790
|
+
return matches;
|
|
791
|
+
},
|
|
792
|
+
transform(sourceFile, matches) {
|
|
793
|
+
if (matches.length === 0) return sourceFile.getFullText();
|
|
794
|
+
let text = sourceFile.getFullText();
|
|
795
|
+
const typedMatches = matches;
|
|
796
|
+
const sortedMatches = [...typedMatches].sort((a, b) => {
|
|
797
|
+
return b.classBodyStart - a.classBodyStart;
|
|
798
|
+
});
|
|
799
|
+
for (const match of sortedMatches) {
|
|
800
|
+
if (!match.hasAttachInternals) {
|
|
801
|
+
const newMember = `\n${match.indent}@AttachInternals() internals: ElementInternals;\n`;
|
|
802
|
+
text = text.slice(0, match.classBodyStart) + newMember + text.slice(match.classBodyStart);
|
|
803
|
+
}
|
|
804
|
+
const prop = match.node;
|
|
805
|
+
const start = prop.getStart();
|
|
806
|
+
let end = prop.getEnd();
|
|
807
|
+
const afterProp = text.slice(end).match(/^\s*,/);
|
|
808
|
+
if (afterProp) end = end + afterProp[0].length;
|
|
809
|
+
text = text.slice(0, start) + text.slice(end);
|
|
810
|
+
}
|
|
811
|
+
const firstMatch = typedMatches[0];
|
|
812
|
+
if (firstMatch?.needsImport && firstMatch.stencilImportEnd > 0) {
|
|
813
|
+
const importMatch = text.match(/import\s*\{([^}]*)\}\s*from\s*['"]@stencil\/core['"]/);
|
|
814
|
+
if (importMatch) {
|
|
815
|
+
const newImports = importMatch[1].trimEnd() + ", AttachInternals";
|
|
816
|
+
text = text.replace(importMatch[0], `import {${newImports}} from '@stencil/core'`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return text;
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region src/migrations/index.ts
|
|
824
|
+
/**
|
|
825
|
+
* Build a map of local import names to their original names from @stencil/core.
|
|
826
|
+
* Handles aliased imports like `import { Component as Cmp } from '@stencil/core'`.
|
|
827
|
+
*
|
|
828
|
+
* @param sourceFile The TypeScript source file to analyze
|
|
829
|
+
* @returns Map where keys are local names and values are original imported names
|
|
830
|
+
*/
|
|
831
|
+
const getStencilCoreImportMap = (sourceFile) => {
|
|
832
|
+
const importMap = /* @__PURE__ */ new Map();
|
|
833
|
+
for (const statement of sourceFile.statements) if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier) && statement.moduleSpecifier.text === "@stencil/core") {
|
|
834
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
835
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) for (const element of namedBindings.elements) {
|
|
836
|
+
const localName = element.name.text;
|
|
837
|
+
const originalName = element.propertyName?.text ?? element.name.text;
|
|
838
|
+
importMap.set(localName, originalName);
|
|
839
|
+
}
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
return importMap;
|
|
843
|
+
};
|
|
844
|
+
/**
|
|
845
|
+
* Check if a decorator identifier refers to a specific @stencil/core export.
|
|
846
|
+
* Handles aliased imports like `import { Component as Cmp } from '@stencil/core'`.
|
|
847
|
+
*
|
|
848
|
+
* @param decoratorName The identifier used in the decorator
|
|
849
|
+
* @param expectedOriginalName The original export name (e.g., 'Component')
|
|
850
|
+
* @param importMap The import map from getStencilCoreImportMap
|
|
851
|
+
* @returns True if the decorator refers to the expected export
|
|
852
|
+
*/
|
|
853
|
+
const isStencilDecorator = (decoratorName, expectedOriginalName, importMap) => {
|
|
854
|
+
return importMap.get(decoratorName) === expectedOriginalName;
|
|
855
|
+
};
|
|
856
|
+
/**
|
|
857
|
+
* Registry of all available migration rules.
|
|
858
|
+
* Rules are applied in order, so add new rules at the end.
|
|
859
|
+
*/
|
|
860
|
+
const migrationRules = [encapsulationApiRule, formAssociatedRule];
|
|
861
|
+
/**
|
|
862
|
+
* Get all migration rules for a specific version upgrade.
|
|
863
|
+
* @param fromVersion Source version (e.g., '4')
|
|
864
|
+
* @param toVersion Target version (e.g., '5')
|
|
865
|
+
* @returns Filtered list of applicable rules
|
|
866
|
+
*/
|
|
867
|
+
const getRulesForVersionUpgrade = (fromVersion, toVersion) => {
|
|
868
|
+
return migrationRules.filter((rule) => rule.fromVersion.startsWith(fromVersion) && rule.toVersion.startsWith(toVersion));
|
|
869
|
+
};
|
|
870
|
+
//#endregion
|
|
871
|
+
//#region src/task-migrate.ts
|
|
872
|
+
/**
|
|
873
|
+
* Run the migration task to update Stencil components from v4 to v5 API.
|
|
874
|
+
*
|
|
875
|
+
* @param coreCompiler the Stencil compiler instance
|
|
876
|
+
* @param config the validated Stencil config
|
|
877
|
+
* @param flags CLI flags (includes dryRun option)
|
|
878
|
+
*/
|
|
879
|
+
const taskMigrate = async (coreCompiler, config, flags) => {
|
|
880
|
+
const logger = config.logger;
|
|
881
|
+
const sys = config.sys;
|
|
882
|
+
const dryRun = flags.dryRun ?? false;
|
|
883
|
+
const currentMajor = coreCompiler.version.split(".")[0];
|
|
884
|
+
const fromVersion = String(Number(currentMajor) - 1);
|
|
885
|
+
const toVersion = currentMajor;
|
|
886
|
+
const rules = getRulesForVersionUpgrade(fromVersion, toVersion);
|
|
887
|
+
if (rules.length === 0) {
|
|
888
|
+
logger.info(`No migration rules found for ${fromVersion}.x → ${toVersion}.x upgrade.`);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
logger.info(`${logger.emoji("🔄 ")}Stencil Migration Tool (v${fromVersion} → v${toVersion})`);
|
|
892
|
+
logger.info(`Scanning for components that need migration...`);
|
|
893
|
+
if (dryRun) logger.info(logger.cyan("Dry run mode - no files will be modified"));
|
|
894
|
+
const tsFiles = await getTypeScriptFiles(config, sys, logger);
|
|
895
|
+
if (tsFiles.length === 0) {
|
|
896
|
+
logger.info(`No TypeScript files found. Check your tsconfig.json configuration.`);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
logger.info(`Found ${tsFiles.length} TypeScript files to scan`);
|
|
900
|
+
const results = [];
|
|
901
|
+
for (const filePath of tsFiles) {
|
|
902
|
+
let content = await sys.readFile(filePath);
|
|
903
|
+
if (!content) continue;
|
|
904
|
+
for (const rule of rules) {
|
|
905
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
906
|
+
const matches = rule.detect(sourceFile);
|
|
907
|
+
if (matches.length > 0) {
|
|
908
|
+
const relPath = relative(config.rootDir, filePath);
|
|
909
|
+
logger.info(`\n${logger.cyan(relPath)}`);
|
|
910
|
+
logger.info(` ${logger.yellow(`[${rule.id}]`)} ${rule.name}`);
|
|
911
|
+
for (const match of matches) logger.info(` Line ${match.line}: ${match.message}`);
|
|
912
|
+
if (!dryRun) {
|
|
913
|
+
const transformed = rule.transform(sourceFile, matches);
|
|
914
|
+
await sys.writeFile(filePath, transformed);
|
|
915
|
+
content = transformed;
|
|
916
|
+
results.push({
|
|
917
|
+
filePath,
|
|
918
|
+
rule,
|
|
919
|
+
matches,
|
|
920
|
+
transformed: true
|
|
921
|
+
});
|
|
922
|
+
logger.info(` ${logger.green("✓")} Migrated`);
|
|
923
|
+
} else results.push({
|
|
924
|
+
filePath,
|
|
925
|
+
rule,
|
|
926
|
+
matches,
|
|
927
|
+
transformed: false
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
logger.info("\n" + logger.bold("Migration Summary"));
|
|
933
|
+
logger.info("─".repeat(40));
|
|
934
|
+
const totalMatches = results.reduce((sum, r) => sum + r.matches.length, 0);
|
|
935
|
+
const filesAffected = new Set(results.map((r) => r.filePath)).size;
|
|
936
|
+
if (totalMatches === 0) logger.info(logger.green("No migrations needed - your code is up to date!"));
|
|
937
|
+
else {
|
|
938
|
+
logger.info(`Found ${totalMatches} item(s) to migrate in ${filesAffected} file(s)`);
|
|
939
|
+
if (dryRun) logger.info(logger.yellow("\nRun without --dry-run to apply the migrations"));
|
|
940
|
+
else logger.info(logger.green(`\n✓ Successfully migrated ${totalMatches} item(s)`));
|
|
941
|
+
}
|
|
942
|
+
const byRule = /* @__PURE__ */ new Map();
|
|
943
|
+
for (const result of results) {
|
|
944
|
+
const existing = byRule.get(result.rule.id) || [];
|
|
945
|
+
existing.push(result);
|
|
946
|
+
byRule.set(result.rule.id, existing);
|
|
947
|
+
}
|
|
948
|
+
if (byRule.size > 0) {
|
|
949
|
+
logger.info("\nBy migration rule:");
|
|
950
|
+
for (const [ruleId, ruleResults] of byRule) {
|
|
951
|
+
const rule = rules.find((r) => r.id === ruleId);
|
|
952
|
+
const count = ruleResults.reduce((sum, r) => sum + r.matches.length, 0);
|
|
953
|
+
logger.info(` ${rule?.name || ruleId}: ${count} item(s)`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
/**
|
|
958
|
+
* Detect available migrations without applying them.
|
|
959
|
+
* Used by the build task to check if migrations might help fix build errors.
|
|
960
|
+
*
|
|
961
|
+
* @param coreCompiler the Stencil compiler instance
|
|
962
|
+
* @param config the validated Stencil config
|
|
963
|
+
* @returns detection result with migration information
|
|
964
|
+
*/
|
|
965
|
+
const detectMigrations = async (coreCompiler, config) => {
|
|
966
|
+
const sys = config.sys;
|
|
967
|
+
const logger = config.logger;
|
|
968
|
+
const currentMajor = coreCompiler.version.split(".")[0];
|
|
969
|
+
const rules = getRulesForVersionUpgrade(String(Number(currentMajor) - 1), currentMajor);
|
|
970
|
+
if (rules.length === 0) return {
|
|
971
|
+
hasMigrations: false,
|
|
972
|
+
totalMatches: 0,
|
|
973
|
+
filesAffected: 0,
|
|
974
|
+
migrations: [],
|
|
975
|
+
rules: []
|
|
976
|
+
};
|
|
977
|
+
const tsFiles = await getTypeScriptFiles(config, sys, logger);
|
|
978
|
+
if (tsFiles.length === 0) return {
|
|
979
|
+
hasMigrations: false,
|
|
980
|
+
totalMatches: 0,
|
|
981
|
+
filesAffected: 0,
|
|
982
|
+
migrations: [],
|
|
983
|
+
rules
|
|
984
|
+
};
|
|
985
|
+
const migrations = [];
|
|
986
|
+
for (const filePath of tsFiles) {
|
|
987
|
+
const content = await sys.readFile(filePath);
|
|
988
|
+
if (!content) continue;
|
|
989
|
+
for (const rule of rules) {
|
|
990
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
991
|
+
const matches = rule.detect(sourceFile);
|
|
992
|
+
if (matches.length > 0) migrations.push({
|
|
993
|
+
filePath,
|
|
994
|
+
rule,
|
|
995
|
+
matches
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
const totalMatches = migrations.reduce((sum, m) => sum + m.matches.length, 0);
|
|
1000
|
+
const filesAffected = new Set(migrations.map((m) => m.filePath)).size;
|
|
1001
|
+
return {
|
|
1002
|
+
hasMigrations: migrations.length > 0,
|
|
1003
|
+
totalMatches,
|
|
1004
|
+
filesAffected,
|
|
1005
|
+
migrations,
|
|
1006
|
+
rules
|
|
1007
|
+
};
|
|
1008
|
+
};
|
|
1009
|
+
/**
|
|
1010
|
+
* Get TypeScript files using the project's tsconfig.json.
|
|
1011
|
+
* Uses the same approach as the Stencil compiler.
|
|
1012
|
+
*
|
|
1013
|
+
* @param config the validated Stencil config
|
|
1014
|
+
* @param sys the compiler system for file operations
|
|
1015
|
+
* @param logger the logger for output
|
|
1016
|
+
* @returns array of absolute paths to TypeScript files
|
|
1017
|
+
*/
|
|
1018
|
+
async function getTypeScriptFiles(config, sys, logger) {
|
|
1019
|
+
let tsconfigPath;
|
|
1020
|
+
if (config.tsconfig) tsconfigPath = isAbsolute(config.tsconfig) ? config.tsconfig : join(config.rootDir, config.tsconfig);
|
|
1021
|
+
else tsconfigPath = join(config.rootDir, "tsconfig.json");
|
|
1022
|
+
logger.debug(`Using tsconfig: ${tsconfigPath}`);
|
|
1023
|
+
const tsconfigContent = await sys.readFile(tsconfigPath);
|
|
1024
|
+
if (!tsconfigContent) {
|
|
1025
|
+
logger.error(`tsconfig not found: ${tsconfigPath}`);
|
|
1026
|
+
return [];
|
|
1027
|
+
}
|
|
1028
|
+
const host = {
|
|
1029
|
+
...ts.sys,
|
|
1030
|
+
readFile: (p) => {
|
|
1031
|
+
if (p === tsconfigPath) return tsconfigContent;
|
|
1032
|
+
return ts.sys.readFile(p);
|
|
1033
|
+
},
|
|
1034
|
+
onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
|
|
1035
|
+
logger.error(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
const results = ts.getParsedCommandLineOfConfigFile(tsconfigPath, {}, host);
|
|
1039
|
+
if (!results) {
|
|
1040
|
+
logger.error(`Failed to parse tsconfig: ${tsconfigPath}`);
|
|
1041
|
+
return [];
|
|
1042
|
+
}
|
|
1043
|
+
if (results.errors && results.errors.length > 0) for (const err of results.errors) logger.warn(ts.flattenDiagnosticMessageText(err.messageText, "\n"));
|
|
1044
|
+
return results.fileNames.filter((f) => (f.endsWith(".ts") || f.endsWith(".tsx")) && !f.endsWith(".d.ts"));
|
|
1045
|
+
}
|
|
1046
|
+
//#endregion
|
|
729
1047
|
//#region src/task-prerender.ts
|
|
730
1048
|
const taskPrerender = async (coreCompiler, config, flags) => {
|
|
731
1049
|
startupCompilerLog(coreCompiler, config);
|
|
@@ -1000,9 +1318,9 @@ function getActiveTargets(config) {
|
|
|
1000
1318
|
* @returns a Promise wrapping data for the telemetry endpoint
|
|
1001
1319
|
*/
|
|
1002
1320
|
const prepareData = async (coreCompiler, config, sys, flags, duration_ms, component_count = void 0) => {
|
|
1003
|
-
const { typescript,
|
|
1321
|
+
const { typescript, rolldown } = coreCompiler.versions || {
|
|
1004
1322
|
typescript: "unknown",
|
|
1005
|
-
|
|
1323
|
+
rolldown: "unknown"
|
|
1006
1324
|
};
|
|
1007
1325
|
const { packages, packagesNoVersions } = await getInstalledPackages(sys, flags);
|
|
1008
1326
|
const targets = getActiveTargets(config);
|
|
@@ -1027,7 +1345,7 @@ const prepareData = async (coreCompiler, config, sys, flags, duration_ms, compon
|
|
|
1027
1345
|
os_version,
|
|
1028
1346
|
packages,
|
|
1029
1347
|
packages_no_versions: packagesNoVersions,
|
|
1030
|
-
|
|
1348
|
+
rolldown,
|
|
1031
1349
|
stencil,
|
|
1032
1350
|
system,
|
|
1033
1351
|
system_major: getMajorVersion(system),
|
|
@@ -1051,13 +1369,11 @@ const CONFIG_PROPS_TO_ANONYMIZE = [
|
|
|
1051
1369
|
"tsconfig"
|
|
1052
1370
|
];
|
|
1053
1371
|
const CONFIG_PROPS_TO_DELETE = [
|
|
1054
|
-
"commonjs",
|
|
1055
1372
|
"devServer",
|
|
1056
1373
|
"env",
|
|
1057
1374
|
"logger",
|
|
1058
|
-
"
|
|
1375
|
+
"rolldownConfig",
|
|
1059
1376
|
"sys",
|
|
1060
|
-
"testing",
|
|
1061
1377
|
"tsCompilerOptions"
|
|
1062
1378
|
];
|
|
1063
1379
|
/**
|
|
@@ -1276,8 +1592,36 @@ const taskBuild = async (coreCompiler, config, flags) => {
|
|
|
1276
1592
|
const results = await compiler.build();
|
|
1277
1593
|
await telemetryBuildFinishedAction(config.sys, config, coreCompiler, results, flags);
|
|
1278
1594
|
await compiler.destroy();
|
|
1279
|
-
if (results.hasError)
|
|
1280
|
-
|
|
1595
|
+
if (results.hasError) {
|
|
1596
|
+
const migrationResult = await detectMigrations(coreCompiler, config);
|
|
1597
|
+
if (migrationResult.hasMigrations) {
|
|
1598
|
+
const action = await promptForMigrationOnBuildError(config, migrationResult);
|
|
1599
|
+
if (action === "run") {
|
|
1600
|
+
await taskMigrate(coreCompiler, config, {
|
|
1601
|
+
...flags,
|
|
1602
|
+
dryRun: false
|
|
1603
|
+
});
|
|
1604
|
+
config.logger.info("\nRe-running build after migrations...\n");
|
|
1605
|
+
const newCompiler = await coreCompiler.createCompiler(config);
|
|
1606
|
+
const newResults = await newCompiler.build();
|
|
1607
|
+
await newCompiler.destroy();
|
|
1608
|
+
if (!newResults.hasError) {
|
|
1609
|
+
exitCode = 0;
|
|
1610
|
+
if (flags.prerender) {
|
|
1611
|
+
const prerenderDiagnostics = await runPrerenderTask(coreCompiler, config, newResults.hydrateAppFilePath, newResults.componentGraph, void 0);
|
|
1612
|
+
config.logger.printDiagnostics(prerenderDiagnostics);
|
|
1613
|
+
if (prerenderDiagnostics.some((d) => d.level === "error")) exitCode = 1;
|
|
1614
|
+
}
|
|
1615
|
+
} else exitCode = 1;
|
|
1616
|
+
} else if (action === "dry-run") {
|
|
1617
|
+
await taskMigrate(coreCompiler, config, {
|
|
1618
|
+
...flags,
|
|
1619
|
+
dryRun: true
|
|
1620
|
+
});
|
|
1621
|
+
exitCode = 1;
|
|
1622
|
+
} else exitCode = 1;
|
|
1623
|
+
} else exitCode = 1;
|
|
1624
|
+
} else if (flags.prerender) {
|
|
1281
1625
|
const prerenderDiagnostics = await runPrerenderTask(coreCompiler, config, results.hydrateAppFilePath, results.componentGraph, void 0);
|
|
1282
1626
|
config.logger.printDiagnostics(prerenderDiagnostics);
|
|
1283
1627
|
if (prerenderDiagnostics.some((d) => d.level === "error")) exitCode = 1;
|
|
@@ -1289,6 +1633,51 @@ const taskBuild = async (coreCompiler, config, flags) => {
|
|
|
1289
1633
|
}
|
|
1290
1634
|
if (exitCode > 0) return config.sys.exit(exitCode);
|
|
1291
1635
|
};
|
|
1636
|
+
/**
|
|
1637
|
+
* Prompt the user about available migrations when a build fails.
|
|
1638
|
+
* Shows what migrations are available and lets them choose to run them.
|
|
1639
|
+
* @param config the Stencil config
|
|
1640
|
+
* @param migrationResult the result of migration detection with available migrations
|
|
1641
|
+
* @returns the user's chosen action for handling migrations
|
|
1642
|
+
*/
|
|
1643
|
+
async function promptForMigrationOnBuildError(config, migrationResult) {
|
|
1644
|
+
const logger = config.logger;
|
|
1645
|
+
logger.info("");
|
|
1646
|
+
logger.info(logger.bold(logger.yellow("Migrations Available")));
|
|
1647
|
+
logger.info("─".repeat(40));
|
|
1648
|
+
logger.info(`Found ${migrationResult.totalMatches} item(s) in ${migrationResult.filesAffected} file(s) that can be automatically migrated.`);
|
|
1649
|
+
for (const migration of migrationResult.migrations) {
|
|
1650
|
+
const relPath = relative(config.rootDir, migration.filePath);
|
|
1651
|
+
logger.info(` ${logger.cyan(relPath)}: ${migration.matches.length} item(s)`);
|
|
1652
|
+
}
|
|
1653
|
+
logger.info("");
|
|
1654
|
+
logger.info("These migrations may help resolve the build errors above.");
|
|
1655
|
+
const { prompt } = await import("prompts");
|
|
1656
|
+
const response = await prompt({
|
|
1657
|
+
name: "action",
|
|
1658
|
+
type: "select",
|
|
1659
|
+
message: "What would you like to do?",
|
|
1660
|
+
choices: [
|
|
1661
|
+
{
|
|
1662
|
+
title: "Run migration",
|
|
1663
|
+
value: "run",
|
|
1664
|
+
description: "Apply migrations and re-run build"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
title: "Dry run",
|
|
1668
|
+
value: "dry-run",
|
|
1669
|
+
description: "Preview changes without modifying files"
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
title: "Exit",
|
|
1673
|
+
value: "exit",
|
|
1674
|
+
description: "Exit without making changes"
|
|
1675
|
+
}
|
|
1676
|
+
]
|
|
1677
|
+
});
|
|
1678
|
+
if (response.action === void 0) return "exit";
|
|
1679
|
+
return response.action;
|
|
1680
|
+
}
|
|
1292
1681
|
//#endregion
|
|
1293
1682
|
//#region src/task-docs.ts
|
|
1294
1683
|
const taskDocs = async (coreCompiler, config) => {
|
|
@@ -1680,7 +2069,7 @@ const taskInfo = (coreCompiler, sys, logger) => {
|
|
|
1680
2069
|
console.log(`${logger.cyan(" Build:")} ${coreCompiler.buildId}`);
|
|
1681
2070
|
console.log(`${logger.cyan(" Stencil:")} ${coreCompiler.version}${logger.emoji(" " + coreCompiler.vermoji)}`);
|
|
1682
2071
|
console.log(`${logger.cyan(" TypeScript:")} ${versions.typescript}`);
|
|
1683
|
-
console.log(`${logger.cyan("
|
|
2072
|
+
console.log(`${logger.cyan(" Rolldown:")} ${versions.rolldown}`);
|
|
1684
2073
|
console.log(`${logger.cyan(" Terser:")} ${versions.terser}`);
|
|
1685
2074
|
console.log(``);
|
|
1686
2075
|
};
|
|
@@ -1810,6 +2199,9 @@ const runTask = async (coreCompiler, config, task, sys, flags) => {
|
|
|
1810
2199
|
case "help":
|
|
1811
2200
|
await taskHelp(resolvedFlags, strictConfig.logger, sys);
|
|
1812
2201
|
break;
|
|
2202
|
+
case "migrate":
|
|
2203
|
+
await taskMigrate(coreCompiler, strictConfig, resolvedFlags);
|
|
2204
|
+
break;
|
|
1813
2205
|
case "prerender":
|
|
1814
2206
|
await taskPrerender(coreCompiler, strictConfig, resolvedFlags);
|
|
1815
2207
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stencil/cli",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.3",
|
|
4
4
|
"description": "CLI for Stencil - Web component compiler",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"prompts": "^2.4.2",
|
|
41
|
-
"@stencil/dev-server": "5.0.0-alpha.
|
|
41
|
+
"@stencil/dev-server": "5.0.0-alpha.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsdown": "^0.21.6",
|
|
45
45
|
"typescript": "~6.0.2",
|
|
46
46
|
"vitest": "^4.1.1",
|
|
47
|
-
"@stencil/core": "5.0.0-alpha.
|
|
47
|
+
"@stencil/core": "5.0.0-alpha.3"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@stencil/core": "^5.0.0-0"
|