@webstir-io/webstir-frontend 0.1.40 → 0.1.41
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/README.md +124 -60
- package/dist/assets/imageOptimizer.js +10 -15
- package/dist/assets/precompression.js +1 -1
- package/dist/builders/contentBuilder.js +102 -90
- package/dist/builders/cssBuilder.js +25 -19
- package/dist/builders/htmlBuilder.js +57 -42
- package/dist/builders/index.js +1 -1
- package/dist/builders/jsBuilder.js +219 -76
- package/dist/builders/staticAssetsBuilder.js +27 -9
- package/dist/builders/types.d.ts +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +6 -30
- package/dist/config/manifest.js +7 -6
- package/dist/config/paths.js +2 -2
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.js +7 -6
- package/dist/config/setup.js +1 -1
- package/dist/config/workspace.js +11 -9
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +5 -5
- package/dist/core/diagnostics.js +1 -1
- package/dist/core/pages.js +4 -4
- package/dist/hooks.js +3 -3
- package/dist/html/criticalCss.js +6 -3
- package/dist/html/htmlSecurity.d.ts +6 -1
- package/dist/html/htmlSecurity.js +28 -14
- package/dist/html/lazyLoad.js +1 -1
- package/dist/html/pageScaffold.js +1 -1
- package/dist/html/resourceHints.js +5 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/inspect.d.ts +2 -0
- package/dist/inspect.js +110 -0
- package/dist/modes/ssg/metadata.js +4 -4
- package/dist/modes/ssg/routing.js +2 -5
- package/dist/modes/ssg/seo.js +5 -5
- package/dist/modes/ssg/views.js +17 -11
- package/dist/operations.js +18 -10
- package/dist/pipeline.d.ts +1 -0
- package/dist/pipeline.js +6 -1
- package/dist/provider.js +28 -24
- package/dist/runtime/boundary.d.ts +28 -0
- package/dist/runtime/boundary.js +247 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/utils/fs.d.ts +11 -10
- package/dist/utils/fs.js +48 -20
- package/dist/utils/glob.d.ts +8 -0
- package/dist/utils/glob.js +21 -0
- package/dist/utils/hash.js +1 -2
- package/dist/utils/pagePaths.js +2 -2
- package/package.json +19 -14
- package/scripts/publish.sh +2 -94
- package/scripts/update-contract.sh +12 -10
- package/src/assets/assetManifest.ts +39 -29
- package/src/assets/imageOptimizer.ts +91 -82
- package/src/assets/precompression.ts +22 -16
- package/src/builders/contentBuilder.ts +1224 -1149
- package/src/builders/cssBuilder.ts +466 -417
- package/src/builders/htmlBuilder.ts +511 -448
- package/src/builders/index.ts +7 -7
- package/src/builders/jsBuilder.ts +538 -280
- package/src/builders/staticAssetsBuilder.ts +166 -135
- package/src/builders/types.ts +7 -6
- package/src/cli.ts +66 -90
- package/src/config/manifest.ts +16 -14
- package/src/config/paths.ts +5 -5
- package/src/config/schema.ts +38 -37
- package/src/config/setup.ts +7 -7
- package/src/config/workspace.ts +118 -116
- package/src/config/workspaceManifest.ts +14 -14
- package/src/core/constants.ts +62 -62
- package/src/core/diagnostics.ts +26 -26
- package/src/core/pages.ts +19 -19
- package/src/hooks.ts +128 -118
- package/src/html/criticalCss.ts +84 -77
- package/src/html/htmlSecurity.ts +107 -66
- package/src/html/lazyLoad.ts +22 -19
- package/src/html/pageScaffold.ts +37 -28
- package/src/html/resourceHints.ts +83 -74
- package/src/index.ts +2 -0
- package/src/inspect.ts +158 -0
- package/src/modes/ssg/metadata.ts +53 -51
- package/src/modes/ssg/routing.ts +177 -177
- package/src/modes/ssg/seo.ts +208 -200
- package/src/modes/ssg/validation.ts +31 -25
- package/src/modes/ssg/views.ts +257 -238
- package/src/operations.ts +105 -95
- package/src/pipeline.ts +81 -69
- package/src/provider.ts +184 -176
- package/src/runtime/boundary.ts +325 -0
- package/src/runtime/index.ts +1 -0
- package/src/types.ts +107 -48
- package/src/utils/changedFile.ts +22 -22
- package/src/utils/fs.ts +73 -26
- package/src/utils/glob.ts +38 -0
- package/src/utils/hash.ts +2 -4
- package/src/utils/pagePaths.ts +35 -23
- package/src/utils/pathMatch.ts +26 -23
- package/tests/add-page-defaults.test.js +44 -39
- package/tests/bundlerParity.test.js +252 -0
- package/tests/cli.contract.test.js +13 -0
- package/tests/content-pages.test.js +108 -13
- package/tests/css-app-imports.test.js +22 -11
- package/tests/css-page-imports.test.js +26 -13
- package/tests/diagnostics.test.js +39 -36
- package/tests/features.test.js +48 -43
- package/tests/hooks.test.js +58 -42
- package/tests/htmlSecurity.test.js +66 -0
- package/tests/inspect.test.js +148 -0
- package/tests/provider.integration.test.js +71 -20
- package/tests/runtime.test.js +493 -0
- package/tests/ssg-defaults.test.js +284 -177
- package/tests/ssg-guardrails.test.js +51 -51
- package/tsconfig.json +3 -10
- package/dist/watch/frontendFiles.d.ts +0 -3
- package/dist/watch/frontendFiles.js +0 -25
- package/dist/watch/hotUpdateTracker.d.ts +0 -51
- package/dist/watch/hotUpdateTracker.js +0 -205
- package/dist/watch/pipelineHelpers.d.ts +0 -26
- package/dist/watch/pipelineHelpers.js +0 -177
- package/dist/watch/types.d.ts +0 -27
- package/dist/watch/types.js +0 -1
- package/dist/watch/watchCoordinator.d.ts +0 -36
- package/dist/watch/watchCoordinator.js +0 -551
- package/dist/watch/watchDaemon.d.ts +0 -17
- package/dist/watch/watchDaemon.js +0 -127
- package/dist/watch/watchReporter.d.ts +0 -21
- package/dist/watch/watchReporter.js +0 -64
- package/scripts/smoke.mjs +0 -35
- package/src/watch/frontendFiles.ts +0 -32
- package/src/watch/hotUpdateTracker.ts +0 -285
- package/src/watch/pipelineHelpers.ts +0 -242
- package/src/watch/types.ts +0 -23
- package/src/watch/watchCoordinator.ts +0 -666
- package/src/watch/watchDaemon.ts +0 -144
- package/src/watch/watchReporter.ts +0 -98
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { BuildResult } from 'esbuild';
|
|
2
|
-
import type { FrontendConfig } from '../types.js';
|
|
3
|
-
import type { BuilderContext } from '../builders/types.js';
|
|
4
|
-
export interface HotAsset {
|
|
5
|
-
readonly type: 'js' | 'css';
|
|
6
|
-
readonly path: string;
|
|
7
|
-
readonly relativePath: string;
|
|
8
|
-
readonly url: string;
|
|
9
|
-
}
|
|
10
|
-
export interface HotUpdateDetails {
|
|
11
|
-
readonly modules: readonly HotAsset[];
|
|
12
|
-
readonly styles: readonly HotAsset[];
|
|
13
|
-
readonly requiresReload: boolean;
|
|
14
|
-
readonly fallbackReasons: readonly string[];
|
|
15
|
-
readonly changedFile?: string;
|
|
16
|
-
readonly stats?: HotUpdateStats;
|
|
17
|
-
}
|
|
18
|
-
export interface HotUpdateStats {
|
|
19
|
-
readonly hotUpdates: number;
|
|
20
|
-
readonly reloadFallbacks: number;
|
|
21
|
-
}
|
|
22
|
-
interface ProcessJavaScriptResult {
|
|
23
|
-
readonly modules: readonly HotAsset[];
|
|
24
|
-
readonly requiresReload: boolean;
|
|
25
|
-
readonly fallbackReasons: readonly string[];
|
|
26
|
-
}
|
|
27
|
-
interface CollectCssResult {
|
|
28
|
-
readonly styles: readonly HotAsset[];
|
|
29
|
-
readonly requiresReload: boolean;
|
|
30
|
-
readonly fallbackReasons: readonly string[];
|
|
31
|
-
}
|
|
32
|
-
interface HotUpdateTrackerOptions {
|
|
33
|
-
readonly workspaceRoot: string;
|
|
34
|
-
}
|
|
35
|
-
export declare class HotUpdateTracker {
|
|
36
|
-
private readonly workspaceRoot;
|
|
37
|
-
private readonly pageOutputHashes;
|
|
38
|
-
private readonly assetFingerprints;
|
|
39
|
-
constructor(options: HotUpdateTrackerOptions);
|
|
40
|
-
reset(): void;
|
|
41
|
-
removePage(pageName: string): void;
|
|
42
|
-
processJavaScriptResult(pageName: string, result: BuildResult, config: FrontendConfig): Promise<ProcessJavaScriptResult>;
|
|
43
|
-
collectCssChanges(context: BuilderContext, pageNames: readonly string[]): Promise<CollectCssResult>;
|
|
44
|
-
private computeAssetFingerprint;
|
|
45
|
-
private getPageCssOutputPath;
|
|
46
|
-
private getAppCssOutputPath;
|
|
47
|
-
private createHotAsset;
|
|
48
|
-
private resolveOutputPath;
|
|
49
|
-
private toWebPath;
|
|
50
|
-
}
|
|
51
|
-
export {};
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import { FOLDERS, FILES, EXTENSIONS } from '../core/constants.js';
|
|
5
|
-
import { emitDiagnostic } from '../core/diagnostics.js';
|
|
6
|
-
import { pathExists } from '../utils/fs.js';
|
|
7
|
-
import { isPathInside } from '../utils/changedFile.js';
|
|
8
|
-
import { findPageFromChangedFile } from '../utils/pathMatch.js';
|
|
9
|
-
export class HotUpdateTracker {
|
|
10
|
-
workspaceRoot;
|
|
11
|
-
pageOutputHashes = new Map();
|
|
12
|
-
assetFingerprints = new Map();
|
|
13
|
-
constructor(options) {
|
|
14
|
-
this.workspaceRoot = options.workspaceRoot;
|
|
15
|
-
}
|
|
16
|
-
reset() {
|
|
17
|
-
this.pageOutputHashes.clear();
|
|
18
|
-
this.assetFingerprints.clear();
|
|
19
|
-
}
|
|
20
|
-
removePage(pageName) {
|
|
21
|
-
this.pageOutputHashes.delete(pageName);
|
|
22
|
-
}
|
|
23
|
-
async processJavaScriptResult(pageName, result, config) {
|
|
24
|
-
const modules = [];
|
|
25
|
-
let requiresReload = false;
|
|
26
|
-
const fallbackReasons = [];
|
|
27
|
-
const metafile = result.metafile;
|
|
28
|
-
if (!metafile) {
|
|
29
|
-
fallbackReasons.push('javascript.metafile.missing');
|
|
30
|
-
return { modules, requiresReload: true, fallbackReasons };
|
|
31
|
-
}
|
|
32
|
-
const buildRoot = config.paths.build.frontend;
|
|
33
|
-
const currentOutputs = new Set();
|
|
34
|
-
const previousOutputs = this.pageOutputHashes.get(pageName) ?? new Map();
|
|
35
|
-
for (const outputPath of Object.keys(metafile.outputs)) {
|
|
36
|
-
const extension = path.extname(outputPath).toLowerCase();
|
|
37
|
-
if (extension !== EXTENSIONS.js && extension !== '.mjs') {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
const absoluteOutput = this.resolveOutputPath(outputPath);
|
|
41
|
-
currentOutputs.add(absoluteOutput);
|
|
42
|
-
const fingerprint = await this.computeAssetFingerprint(absoluteOutput, buildRoot, 'js');
|
|
43
|
-
if (!fingerprint) {
|
|
44
|
-
if (this.assetFingerprints.has(absoluteOutput)) {
|
|
45
|
-
this.assetFingerprints.delete(absoluteOutput);
|
|
46
|
-
}
|
|
47
|
-
if (previousOutputs.has(absoluteOutput)) {
|
|
48
|
-
previousOutputs.delete(absoluteOutput);
|
|
49
|
-
requiresReload = true;
|
|
50
|
-
fallbackReasons.push('javascript.output.missing');
|
|
51
|
-
}
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
if (fingerprint.requiresReload) {
|
|
55
|
-
requiresReload = true;
|
|
56
|
-
fallbackReasons.push('javascript.fingerprint.error');
|
|
57
|
-
}
|
|
58
|
-
if (fingerprint.changed) {
|
|
59
|
-
modules.push(fingerprint.asset);
|
|
60
|
-
}
|
|
61
|
-
if (fingerprint.hash) {
|
|
62
|
-
previousOutputs.set(absoluteOutput, { hash: fingerprint.hash });
|
|
63
|
-
}
|
|
64
|
-
else if (previousOutputs.has(absoluteOutput)) {
|
|
65
|
-
previousOutputs.delete(absoluteOutput);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
for (const known of Array.from(previousOutputs.keys())) {
|
|
69
|
-
if (!currentOutputs.has(known)) {
|
|
70
|
-
previousOutputs.delete(known);
|
|
71
|
-
requiresReload = true;
|
|
72
|
-
fallbackReasons.push('javascript.output.removed');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
this.pageOutputHashes.set(pageName, previousOutputs);
|
|
76
|
-
return { modules, requiresReload, fallbackReasons: uniqueReasons(fallbackReasons) };
|
|
77
|
-
}
|
|
78
|
-
async collectCssChanges(context, pageNames) {
|
|
79
|
-
const { config, changedFile } = context;
|
|
80
|
-
const buildRoot = config.paths.build.frontend;
|
|
81
|
-
const candidates = new Set();
|
|
82
|
-
if (!changedFile) {
|
|
83
|
-
for (const page of pageNames) {
|
|
84
|
-
candidates.add(this.getPageCssOutputPath(config, page));
|
|
85
|
-
}
|
|
86
|
-
candidates.add(this.getAppCssOutputPath(config));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const normalized = path.resolve(changedFile);
|
|
90
|
-
const extension = path.extname(normalized).toLowerCase();
|
|
91
|
-
if (extension === EXTENSIONS.css) {
|
|
92
|
-
if (isPathInside(normalized, config.paths.src.app)) {
|
|
93
|
-
for (const page of pageNames) {
|
|
94
|
-
candidates.add(this.getPageCssOutputPath(config, page));
|
|
95
|
-
}
|
|
96
|
-
candidates.add(this.getAppCssOutputPath(config));
|
|
97
|
-
}
|
|
98
|
-
else if (isPathInside(normalized, config.paths.src.pages)) {
|
|
99
|
-
const page = findPageFromChangedFile(normalized, config.paths.src.pages);
|
|
100
|
-
if (page) {
|
|
101
|
-
candidates.add(this.getPageCssOutputPath(config, page));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else if (isPathInside(normalized, config.paths.src.frontend)) {
|
|
105
|
-
for (const page of pageNames) {
|
|
106
|
-
candidates.add(this.getPageCssOutputPath(config, page));
|
|
107
|
-
}
|
|
108
|
-
candidates.add(this.getAppCssOutputPath(config));
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (candidates.size === 0 && !changedFile) {
|
|
113
|
-
candidates.add(this.getAppCssOutputPath(config));
|
|
114
|
-
for (const page of pageNames) {
|
|
115
|
-
candidates.add(this.getPageCssOutputPath(config, page));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const styles = [];
|
|
119
|
-
let requiresReload = !changedFile;
|
|
120
|
-
const fallbackReasons = [];
|
|
121
|
-
if (!changedFile) {
|
|
122
|
-
fallbackReasons.push('css.full-rebuild');
|
|
123
|
-
}
|
|
124
|
-
for (const candidate of candidates) {
|
|
125
|
-
const fingerprint = await this.computeAssetFingerprint(candidate, buildRoot, 'css');
|
|
126
|
-
if (!fingerprint) {
|
|
127
|
-
if (this.assetFingerprints.has(path.resolve(candidate))) {
|
|
128
|
-
this.assetFingerprints.delete(path.resolve(candidate));
|
|
129
|
-
requiresReload = true;
|
|
130
|
-
fallbackReasons.push('css.asset.missing');
|
|
131
|
-
}
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
if (fingerprint.requiresReload) {
|
|
135
|
-
requiresReload = true;
|
|
136
|
-
fallbackReasons.push('css.fingerprint.error');
|
|
137
|
-
}
|
|
138
|
-
if (fingerprint.changed) {
|
|
139
|
-
styles.push(fingerprint.asset);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return { styles, requiresReload, fallbackReasons: uniqueReasons(fallbackReasons) };
|
|
143
|
-
}
|
|
144
|
-
async computeAssetFingerprint(filePath, buildRoot, type) {
|
|
145
|
-
const absolutePath = path.resolve(filePath);
|
|
146
|
-
if (!(await pathExists(absolutePath))) {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
try {
|
|
150
|
-
const contents = await readFile(absolutePath);
|
|
151
|
-
const hash = createHash('sha1').update(contents).digest('hex');
|
|
152
|
-
const previous = this.assetFingerprints.get(absolutePath);
|
|
153
|
-
const changed = previous !== hash;
|
|
154
|
-
this.assetFingerprints.set(absolutePath, hash);
|
|
155
|
-
return {
|
|
156
|
-
asset: this.createHotAsset(absolutePath, buildRoot, type),
|
|
157
|
-
changed,
|
|
158
|
-
requiresReload: false,
|
|
159
|
-
hash
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
emitDiagnostic({
|
|
164
|
-
code: 'frontend.watch.unexpected',
|
|
165
|
-
kind: 'watch-daemon',
|
|
166
|
-
stage: 'css-fingerprint',
|
|
167
|
-
severity: 'error',
|
|
168
|
-
message: `Failed to fingerprint asset '${absolutePath}': ${error instanceof Error ? error.message : String(error)}`
|
|
169
|
-
});
|
|
170
|
-
return {
|
|
171
|
-
asset: this.createHotAsset(absolutePath, buildRoot, type),
|
|
172
|
-
changed: false,
|
|
173
|
-
requiresReload: true
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
getPageCssOutputPath(config, pageName) {
|
|
178
|
-
return path.join(config.paths.build.frontend, FOLDERS.pages, pageName, `${FILES.index}${EXTENSIONS.css}`);
|
|
179
|
-
}
|
|
180
|
-
getAppCssOutputPath(config) {
|
|
181
|
-
return path.join(config.paths.build.frontend, FOLDERS.app, 'app.css');
|
|
182
|
-
}
|
|
183
|
-
createHotAsset(filePath, buildRoot, type) {
|
|
184
|
-
const relativePath = path.relative(buildRoot, filePath);
|
|
185
|
-
const webPath = this.toWebPath(relativePath);
|
|
186
|
-
return {
|
|
187
|
-
type,
|
|
188
|
-
path: filePath,
|
|
189
|
-
relativePath,
|
|
190
|
-
url: webPath.startsWith('/') ? webPath : `/${webPath}`
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
resolveOutputPath(outputPath) {
|
|
194
|
-
if (path.isAbsolute(outputPath)) {
|
|
195
|
-
return outputPath;
|
|
196
|
-
}
|
|
197
|
-
return path.resolve(this.workspaceRoot, outputPath);
|
|
198
|
-
}
|
|
199
|
-
toWebPath(relativePath) {
|
|
200
|
-
return relativePath.split(path.sep).join('/') || '';
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
function uniqueReasons(reasons) {
|
|
204
|
-
return Array.from(new Set(reasons.filter(Boolean)));
|
|
205
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { Builder, BuilderContext } from '../builders/types.js';
|
|
2
|
-
import { WatchReporter, type SerializedMessage } from './watchReporter.js';
|
|
3
|
-
import type { HotAsset, HotUpdateDetails } from './hotUpdateTracker.js';
|
|
4
|
-
export interface JavaScriptBuildSummary {
|
|
5
|
-
readonly pagesBuilt: readonly string[];
|
|
6
|
-
readonly warnings: readonly SerializedMessage[];
|
|
7
|
-
readonly modules: readonly HotAsset[];
|
|
8
|
-
readonly requiresReload: boolean;
|
|
9
|
-
readonly fallbackReasons: readonly string[];
|
|
10
|
-
}
|
|
11
|
-
export interface AdditionalBuildResult {
|
|
12
|
-
readonly succeeded: boolean;
|
|
13
|
-
readonly assets: readonly string[];
|
|
14
|
-
readonly styles: readonly HotAsset[];
|
|
15
|
-
readonly requiresReload: boolean;
|
|
16
|
-
readonly fallbackReasons: readonly string[];
|
|
17
|
-
}
|
|
18
|
-
export declare function runBuilderWithDiagnostics(builder: Builder, reporter: WatchReporter, context: BuilderContext, changedFile: string | undefined, relativeChange: string | undefined): Promise<boolean>;
|
|
19
|
-
export declare function emitPipelineSuccess(summary: JavaScriptBuildSummary, assetsResult: AdditionalBuildResult, changedFile: string | undefined, relativeChange: string | undefined, hotUpdate: HotUpdateDetails): void;
|
|
20
|
-
export declare function serializeSummary(summary: JavaScriptBuildSummary, changedFile: string | undefined, skipped: boolean): Record<string, unknown>;
|
|
21
|
-
export declare function emitJavaScriptFailure(error: unknown, changedFile?: string): void;
|
|
22
|
-
export declare class JavaScriptBuildError extends Error {
|
|
23
|
-
readonly pageName: string;
|
|
24
|
-
readonly details: readonly SerializedMessage[];
|
|
25
|
-
constructor(pageName: string, cause: unknown);
|
|
26
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { emitDiagnostic } from '../core/diagnostics.js';
|
|
2
|
-
import { serializeMessages } from './watchReporter.js';
|
|
3
|
-
const BUILDER_DISPLAY_NAMES = {
|
|
4
|
-
css: 'CSS',
|
|
5
|
-
html: 'HTML',
|
|
6
|
-
'static-assets': 'Static assets'
|
|
7
|
-
};
|
|
8
|
-
export async function runBuilderWithDiagnostics(builder, reporter, context, changedFile, relativeChange) {
|
|
9
|
-
const displayName = BUILDER_DISPLAY_NAMES[builder.name] ?? builder.name;
|
|
10
|
-
const messageContext = relativeChange ? ` (${relativeChange})` : '';
|
|
11
|
-
reporter.emitVerbose({
|
|
12
|
-
code: `frontend.watch.${builder.name}.build.start`,
|
|
13
|
-
kind: 'watch-daemon',
|
|
14
|
-
stage: builder.name,
|
|
15
|
-
severity: 'info',
|
|
16
|
-
message: `Starting ${displayName} rebuild${messageContext}.`,
|
|
17
|
-
data: changedFile ? { changedFile, builder: builder.name } : { builder: builder.name }
|
|
18
|
-
});
|
|
19
|
-
try {
|
|
20
|
-
await builder.build(context);
|
|
21
|
-
reporter.emitVerbose({
|
|
22
|
-
code: `frontend.watch.${builder.name}.build.success`,
|
|
23
|
-
kind: 'watch-daemon',
|
|
24
|
-
stage: builder.name,
|
|
25
|
-
severity: 'info',
|
|
26
|
-
message: `${displayName} rebuild completed${messageContext}.`,
|
|
27
|
-
data: changedFile ? { changedFile, builder: builder.name } : { builder: builder.name }
|
|
28
|
-
});
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
const details = { builder: builder.name };
|
|
33
|
-
if (changedFile) {
|
|
34
|
-
details.changedFile = changedFile;
|
|
35
|
-
}
|
|
36
|
-
if (error instanceof Error) {
|
|
37
|
-
details.error = error.message;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
details.error = String(error);
|
|
41
|
-
}
|
|
42
|
-
emitDiagnostic({
|
|
43
|
-
code: `frontend.watch.${builder.name}.build.failure`,
|
|
44
|
-
kind: 'watch-daemon',
|
|
45
|
-
stage: builder.name,
|
|
46
|
-
severity: 'error',
|
|
47
|
-
message: `${displayName} rebuild failed${messageContext}.`,
|
|
48
|
-
data: details
|
|
49
|
-
});
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
export function emitPipelineSuccess(summary, assetsResult, changedFile, relativeChange, hotUpdate) {
|
|
54
|
-
const message = `Frontend rebuild pipeline completed${relativeChange ? ` (${relativeChange})` : ''}.`;
|
|
55
|
-
const data = {
|
|
56
|
-
pages: summary.pagesBuilt,
|
|
57
|
-
assets: assetsResult.assets,
|
|
58
|
-
hotUpdate: serializeHotUpdate(hotUpdate, relativeChange)
|
|
59
|
-
};
|
|
60
|
-
if (relativeChange) {
|
|
61
|
-
data.changedFile = relativeChange;
|
|
62
|
-
}
|
|
63
|
-
else if (changedFile) {
|
|
64
|
-
data.changedFile = changedFile;
|
|
65
|
-
}
|
|
66
|
-
if (summary.warnings.length > 0) {
|
|
67
|
-
data.javascriptWarnings = summary.warnings;
|
|
68
|
-
}
|
|
69
|
-
emitDiagnostic({
|
|
70
|
-
code: 'frontend.watch.pipeline.success',
|
|
71
|
-
kind: 'watch-daemon',
|
|
72
|
-
stage: 'pipeline',
|
|
73
|
-
severity: 'info',
|
|
74
|
-
message,
|
|
75
|
-
data
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
export function serializeSummary(summary, changedFile, skipped) {
|
|
79
|
-
const data = {
|
|
80
|
-
pages: summary.pagesBuilt
|
|
81
|
-
};
|
|
82
|
-
if (changedFile) {
|
|
83
|
-
data.changedFile = changedFile;
|
|
84
|
-
}
|
|
85
|
-
if (summary.warnings.length > 0) {
|
|
86
|
-
data.warnings = summary.warnings;
|
|
87
|
-
}
|
|
88
|
-
if (skipped) {
|
|
89
|
-
data.skipped = true;
|
|
90
|
-
}
|
|
91
|
-
if (summary.modules.length > 0) {
|
|
92
|
-
data.modules = summary.modules.map(asset => asset.url);
|
|
93
|
-
}
|
|
94
|
-
if (summary.requiresReload) {
|
|
95
|
-
data.requiresReload = true;
|
|
96
|
-
}
|
|
97
|
-
if (summary.fallbackReasons.length > 0) {
|
|
98
|
-
data.fallbackReasons = summary.fallbackReasons;
|
|
99
|
-
}
|
|
100
|
-
return data;
|
|
101
|
-
}
|
|
102
|
-
export function emitJavaScriptFailure(error, changedFile) {
|
|
103
|
-
let message = 'JavaScript rebuild failed.';
|
|
104
|
-
let severity = 'error';
|
|
105
|
-
const data = changedFile ? { changedFile } : {};
|
|
106
|
-
if (error instanceof JavaScriptBuildError) {
|
|
107
|
-
message = `JavaScript rebuild failed for page '${error.pageName}'.`;
|
|
108
|
-
if (error.details.length > 0) {
|
|
109
|
-
data.errors = error.details;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else if (error instanceof Error) {
|
|
113
|
-
message = `JavaScript rebuild failed: ${error.message}`;
|
|
114
|
-
}
|
|
115
|
-
emitDiagnostic({
|
|
116
|
-
code: 'frontend.watch.javascript.build.failure',
|
|
117
|
-
kind: 'watch-daemon',
|
|
118
|
-
stage: 'javascript',
|
|
119
|
-
severity,
|
|
120
|
-
message,
|
|
121
|
-
data: Object.keys(data).length > 0 ? data : undefined
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
export class JavaScriptBuildError extends Error {
|
|
125
|
-
pageName;
|
|
126
|
-
details;
|
|
127
|
-
constructor(pageName, cause) {
|
|
128
|
-
const message = cause instanceof Error ? cause.message : String(cause);
|
|
129
|
-
super(message);
|
|
130
|
-
this.pageName = pageName;
|
|
131
|
-
this.details = isBuildFailure(cause) ? serializeMessages(cause.errors ?? []) : [];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
function serializeHotUpdate(hotUpdate, relativeChange) {
|
|
135
|
-
const data = {
|
|
136
|
-
requiresReload: hotUpdate.requiresReload,
|
|
137
|
-
modules: hotUpdate.modules.map(asset => serializeHotAsset(asset)),
|
|
138
|
-
styles: hotUpdate.styles.map(asset => serializeHotAsset(asset))
|
|
139
|
-
};
|
|
140
|
-
if (relativeChange) {
|
|
141
|
-
data.changedFile = relativeChange;
|
|
142
|
-
}
|
|
143
|
-
else if (hotUpdate.changedFile) {
|
|
144
|
-
data.changedFile = hotUpdate.changedFile;
|
|
145
|
-
}
|
|
146
|
-
if (hotUpdate.fallbackReasons.length > 0) {
|
|
147
|
-
data.fallbackReasons = hotUpdate.fallbackReasons;
|
|
148
|
-
}
|
|
149
|
-
if (hotUpdate.stats) {
|
|
150
|
-
data.stats = {
|
|
151
|
-
hotUpdates: hotUpdate.stats.hotUpdates,
|
|
152
|
-
reloadFallbacks: hotUpdate.stats.reloadFallbacks
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
return data;
|
|
156
|
-
}
|
|
157
|
-
function serializeHotAsset(asset) {
|
|
158
|
-
return {
|
|
159
|
-
type: asset.type,
|
|
160
|
-
path: asset.path,
|
|
161
|
-
relativePath: asset.relativePath,
|
|
162
|
-
url: asset.url
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function isBuildFailure(error) {
|
|
166
|
-
if (typeof error !== 'object' || error === null) {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
const candidate = error;
|
|
170
|
-
return Array.isArray(candidate.errors) && candidate.errors.every(isEsbuildMessage);
|
|
171
|
-
}
|
|
172
|
-
function isEsbuildMessage(candidate) {
|
|
173
|
-
if (typeof candidate !== 'object' || candidate === null) {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
return typeof candidate.text === 'string';
|
|
177
|
-
}
|
package/dist/watch/types.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export type WatchDaemonCommand = {
|
|
2
|
-
readonly type: 'start';
|
|
3
|
-
} | {
|
|
4
|
-
readonly type: 'change';
|
|
5
|
-
readonly path: string;
|
|
6
|
-
} | {
|
|
7
|
-
readonly type: 'reload';
|
|
8
|
-
} | {
|
|
9
|
-
readonly type: 'shutdown';
|
|
10
|
-
} | {
|
|
11
|
-
readonly type: 'ping';
|
|
12
|
-
readonly id?: string;
|
|
13
|
-
};
|
|
14
|
-
export interface WatchDaemonOptions {
|
|
15
|
-
readonly workspaceRoot: string;
|
|
16
|
-
readonly autoStart?: boolean;
|
|
17
|
-
readonly verbose?: boolean;
|
|
18
|
-
readonly hmrVerbose?: boolean;
|
|
19
|
-
}
|
|
20
|
-
export interface WatchCoordinatorOptions {
|
|
21
|
-
readonly workspaceRoot: string;
|
|
22
|
-
readonly verbose?: boolean;
|
|
23
|
-
readonly hmrVerbose?: boolean;
|
|
24
|
-
}
|
|
25
|
-
export interface WatchChangeIntent {
|
|
26
|
-
readonly path?: string;
|
|
27
|
-
}
|
package/dist/watch/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { WatchChangeIntent, WatchCoordinatorOptions } from './types.js';
|
|
2
|
-
export declare class WatchCoordinator {
|
|
3
|
-
private readonly workspaceRoot;
|
|
4
|
-
private readonly jsContexts;
|
|
5
|
-
private readonly verbose;
|
|
6
|
-
private readonly hmrVerbose;
|
|
7
|
-
private readonly reporter;
|
|
8
|
-
private readonly hotUpdateTracker;
|
|
9
|
-
private readonly hmrTotals;
|
|
10
|
-
private config?;
|
|
11
|
-
private isSsgWorkspace;
|
|
12
|
-
private enable?;
|
|
13
|
-
private isStopping;
|
|
14
|
-
private queue;
|
|
15
|
-
constructor(options: WatchCoordinatorOptions);
|
|
16
|
-
start(): Promise<void>;
|
|
17
|
-
reload(): Promise<void>;
|
|
18
|
-
handleChange(intent: WatchChangeIntent): Promise<void>;
|
|
19
|
-
stop(): Promise<void>;
|
|
20
|
-
private enqueue;
|
|
21
|
-
private refreshJavaScriptContexts;
|
|
22
|
-
private ensureJavaScriptContext;
|
|
23
|
-
private runFullBuildCycle;
|
|
24
|
-
private runAdditionalBuilders;
|
|
25
|
-
private getRelativeChange;
|
|
26
|
-
private runJavaScriptBuild;
|
|
27
|
-
private executeJavaScriptBuild;
|
|
28
|
-
private readWorkspaceSettings;
|
|
29
|
-
private resolveTargetPages;
|
|
30
|
-
private resolveChangedFile;
|
|
31
|
-
private emitHotUpdateFallback;
|
|
32
|
-
private recordHotUpdateOutcome;
|
|
33
|
-
private combineFallbackReasons;
|
|
34
|
-
private requireConfig;
|
|
35
|
-
private logUnexpectedError;
|
|
36
|
-
}
|