@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.
Files changed (138) hide show
  1. package/README.md +124 -60
  2. package/dist/assets/imageOptimizer.js +10 -15
  3. package/dist/assets/precompression.js +1 -1
  4. package/dist/builders/contentBuilder.js +102 -90
  5. package/dist/builders/cssBuilder.js +25 -19
  6. package/dist/builders/htmlBuilder.js +57 -42
  7. package/dist/builders/index.js +1 -1
  8. package/dist/builders/jsBuilder.js +219 -76
  9. package/dist/builders/staticAssetsBuilder.js +27 -9
  10. package/dist/builders/types.d.ts +1 -0
  11. package/dist/cli.d.ts +1 -1
  12. package/dist/cli.js +6 -30
  13. package/dist/config/manifest.js +7 -6
  14. package/dist/config/paths.js +2 -2
  15. package/dist/config/schema.d.ts +8 -0
  16. package/dist/config/schema.js +7 -6
  17. package/dist/config/setup.js +1 -1
  18. package/dist/config/workspace.js +11 -9
  19. package/dist/core/constants.d.ts +1 -1
  20. package/dist/core/constants.js +5 -5
  21. package/dist/core/diagnostics.js +1 -1
  22. package/dist/core/pages.js +4 -4
  23. package/dist/hooks.js +3 -3
  24. package/dist/html/criticalCss.js +6 -3
  25. package/dist/html/htmlSecurity.d.ts +6 -1
  26. package/dist/html/htmlSecurity.js +28 -14
  27. package/dist/html/lazyLoad.js +1 -1
  28. package/dist/html/pageScaffold.js +1 -1
  29. package/dist/html/resourceHints.js +5 -2
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +2 -0
  32. package/dist/inspect.d.ts +2 -0
  33. package/dist/inspect.js +110 -0
  34. package/dist/modes/ssg/metadata.js +4 -4
  35. package/dist/modes/ssg/routing.js +2 -5
  36. package/dist/modes/ssg/seo.js +5 -5
  37. package/dist/modes/ssg/views.js +17 -11
  38. package/dist/operations.js +18 -10
  39. package/dist/pipeline.d.ts +1 -0
  40. package/dist/pipeline.js +6 -1
  41. package/dist/provider.js +28 -24
  42. package/dist/runtime/boundary.d.ts +28 -0
  43. package/dist/runtime/boundary.js +247 -0
  44. package/dist/runtime/index.d.ts +1 -0
  45. package/dist/runtime/index.js +1 -0
  46. package/dist/types.d.ts +52 -0
  47. package/dist/utils/fs.d.ts +11 -10
  48. package/dist/utils/fs.js +48 -20
  49. package/dist/utils/glob.d.ts +8 -0
  50. package/dist/utils/glob.js +21 -0
  51. package/dist/utils/hash.js +1 -2
  52. package/dist/utils/pagePaths.js +2 -2
  53. package/package.json +19 -14
  54. package/scripts/publish.sh +2 -94
  55. package/scripts/update-contract.sh +12 -10
  56. package/src/assets/assetManifest.ts +39 -29
  57. package/src/assets/imageOptimizer.ts +91 -82
  58. package/src/assets/precompression.ts +22 -16
  59. package/src/builders/contentBuilder.ts +1224 -1149
  60. package/src/builders/cssBuilder.ts +466 -417
  61. package/src/builders/htmlBuilder.ts +511 -448
  62. package/src/builders/index.ts +7 -7
  63. package/src/builders/jsBuilder.ts +538 -280
  64. package/src/builders/staticAssetsBuilder.ts +166 -135
  65. package/src/builders/types.ts +7 -6
  66. package/src/cli.ts +66 -90
  67. package/src/config/manifest.ts +16 -14
  68. package/src/config/paths.ts +5 -5
  69. package/src/config/schema.ts +38 -37
  70. package/src/config/setup.ts +7 -7
  71. package/src/config/workspace.ts +118 -116
  72. package/src/config/workspaceManifest.ts +14 -14
  73. package/src/core/constants.ts +62 -62
  74. package/src/core/diagnostics.ts +26 -26
  75. package/src/core/pages.ts +19 -19
  76. package/src/hooks.ts +128 -118
  77. package/src/html/criticalCss.ts +84 -77
  78. package/src/html/htmlSecurity.ts +107 -66
  79. package/src/html/lazyLoad.ts +22 -19
  80. package/src/html/pageScaffold.ts +37 -28
  81. package/src/html/resourceHints.ts +83 -74
  82. package/src/index.ts +2 -0
  83. package/src/inspect.ts +158 -0
  84. package/src/modes/ssg/metadata.ts +53 -51
  85. package/src/modes/ssg/routing.ts +177 -177
  86. package/src/modes/ssg/seo.ts +208 -200
  87. package/src/modes/ssg/validation.ts +31 -25
  88. package/src/modes/ssg/views.ts +257 -238
  89. package/src/operations.ts +105 -95
  90. package/src/pipeline.ts +81 -69
  91. package/src/provider.ts +184 -176
  92. package/src/runtime/boundary.ts +325 -0
  93. package/src/runtime/index.ts +1 -0
  94. package/src/types.ts +107 -48
  95. package/src/utils/changedFile.ts +22 -22
  96. package/src/utils/fs.ts +73 -26
  97. package/src/utils/glob.ts +38 -0
  98. package/src/utils/hash.ts +2 -4
  99. package/src/utils/pagePaths.ts +35 -23
  100. package/src/utils/pathMatch.ts +26 -23
  101. package/tests/add-page-defaults.test.js +44 -39
  102. package/tests/bundlerParity.test.js +252 -0
  103. package/tests/cli.contract.test.js +13 -0
  104. package/tests/content-pages.test.js +108 -13
  105. package/tests/css-app-imports.test.js +22 -11
  106. package/tests/css-page-imports.test.js +26 -13
  107. package/tests/diagnostics.test.js +39 -36
  108. package/tests/features.test.js +48 -43
  109. package/tests/hooks.test.js +58 -42
  110. package/tests/htmlSecurity.test.js +66 -0
  111. package/tests/inspect.test.js +148 -0
  112. package/tests/provider.integration.test.js +71 -20
  113. package/tests/runtime.test.js +493 -0
  114. package/tests/ssg-defaults.test.js +284 -177
  115. package/tests/ssg-guardrails.test.js +51 -51
  116. package/tsconfig.json +3 -10
  117. package/dist/watch/frontendFiles.d.ts +0 -3
  118. package/dist/watch/frontendFiles.js +0 -25
  119. package/dist/watch/hotUpdateTracker.d.ts +0 -51
  120. package/dist/watch/hotUpdateTracker.js +0 -205
  121. package/dist/watch/pipelineHelpers.d.ts +0 -26
  122. package/dist/watch/pipelineHelpers.js +0 -177
  123. package/dist/watch/types.d.ts +0 -27
  124. package/dist/watch/types.js +0 -1
  125. package/dist/watch/watchCoordinator.d.ts +0 -36
  126. package/dist/watch/watchCoordinator.js +0 -551
  127. package/dist/watch/watchDaemon.d.ts +0 -17
  128. package/dist/watch/watchDaemon.js +0 -127
  129. package/dist/watch/watchReporter.d.ts +0 -21
  130. package/dist/watch/watchReporter.js +0 -64
  131. package/scripts/smoke.mjs +0 -35
  132. package/src/watch/frontendFiles.ts +0 -32
  133. package/src/watch/hotUpdateTracker.ts +0 -285
  134. package/src/watch/pipelineHelpers.ts +0 -242
  135. package/src/watch/types.ts +0 -23
  136. package/src/watch/watchCoordinator.ts +0 -666
  137. package/src/watch/watchDaemon.ts +0 -144
  138. package/src/watch/watchReporter.ts +0 -98
@@ -1,144 +0,0 @@
1
- import process from 'node:process';
2
- import { createInterface, Interface as ReadLineInterface } from 'node:readline';
3
- import { emitDiagnostic } from '../core/diagnostics.js';
4
- import { WatchCoordinator } from './watchCoordinator.js';
5
- import type { WatchDaemonCommand, WatchDaemonOptions } from './types.js';
6
-
7
- export class WatchDaemon {
8
- private readonly coordinator: WatchCoordinator;
9
- private readonly options: WatchDaemonOptions;
10
- private readonly shutdownPromise: Promise<void>;
11
- private resolveShutdown: (() => void) | null = null;
12
- private commandQueue: Promise<void> = Promise.resolve();
13
- private isShuttingDown = false;
14
- private rl?: ReadLineInterface;
15
-
16
- public constructor(options: WatchDaemonOptions) {
17
- this.options = options;
18
- this.coordinator = new WatchCoordinator({
19
- workspaceRoot: options.workspaceRoot,
20
- verbose: options.verbose ?? false,
21
- hmrVerbose: options.hmrVerbose ?? false
22
- });
23
- this.shutdownPromise = new Promise((resolve) => {
24
- this.resolveShutdown = resolve;
25
- });
26
- }
27
-
28
- public async run(): Promise<void> {
29
- if (this.options.autoStart !== false) {
30
- await this.coordinator.start();
31
- }
32
-
33
- this.setupSignalHandlers();
34
- this.setupCommandLoop();
35
-
36
- await this.shutdownPromise;
37
- }
38
-
39
- private setupCommandLoop(): void {
40
- if (process.stdin.isTTY) {
41
- process.stdin.setRawMode(false);
42
- }
43
- process.stdin.setEncoding('utf8');
44
-
45
- this.rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
46
- this.rl.on('line', (line) => this.processLine(line));
47
- this.rl.on('close', () => {
48
- void this.shutdown();
49
- });
50
- }
51
-
52
- private setupSignalHandlers(): void {
53
- const shutdown = () => {
54
- void this.shutdown();
55
- };
56
-
57
- process.on('SIGINT', shutdown);
58
- process.on('SIGTERM', shutdown);
59
- }
60
-
61
- private processLine(rawLine: string): void {
62
- const line = rawLine.trim();
63
- if (line.length === 0) {
64
- return;
65
- }
66
-
67
- let command: WatchDaemonCommand | null = null;
68
- try {
69
- command = JSON.parse(line) as WatchDaemonCommand;
70
- } catch (error) {
71
- emitDiagnostic({
72
- code: 'frontend.watch.command.invalid',
73
- kind: 'watch-daemon',
74
- stage: 'command',
75
- severity: 'warning',
76
- message: `Discarding invalid command payload: ${String(error)}`
77
- });
78
- return;
79
- }
80
-
81
- this.commandQueue = this.commandQueue.then(() => this.handleCommand(command!)).catch((error) => {
82
- emitDiagnostic({
83
- code: 'frontend.watch.command.failure',
84
- kind: 'watch-daemon',
85
- stage: 'command',
86
- severity: 'error',
87
- message: `Command handling failed: ${error instanceof Error ? error.message : String(error)}`
88
- });
89
- });
90
- }
91
-
92
- private async handleCommand(command: WatchDaemonCommand): Promise<void> {
93
- switch (command.type) {
94
- case 'start':
95
- await this.coordinator.start();
96
- return;
97
- case 'reload':
98
- await this.coordinator.reload();
99
- return;
100
- case 'change':
101
- await this.coordinator.handleChange({ path: command.path });
102
- return;
103
- case 'shutdown':
104
- await this.shutdown();
105
- return;
106
- case 'ping':
107
- emitDiagnostic({
108
- code: 'frontend.watch.pong',
109
- kind: 'watch-daemon',
110
- stage: 'command',
111
- severity: 'info',
112
- message: 'Watch daemon heartbeat acknowledged.',
113
- data: command.id ? { id: command.id } : undefined
114
- });
115
- return;
116
- default:
117
- emitDiagnostic({
118
- code: 'frontend.watch.command.unknown',
119
- kind: 'watch-daemon',
120
- stage: 'command',
121
- severity: 'warning',
122
- message: `Unknown watch daemon command: ${(command as { type?: unknown }).type}`
123
- });
124
- return;
125
- }
126
- }
127
-
128
- private async shutdown(): Promise<void> {
129
- if (this.isShuttingDown) {
130
- return;
131
- }
132
-
133
- this.isShuttingDown = true;
134
-
135
- if (this.rl) {
136
- this.rl.close();
137
- this.rl = undefined;
138
- }
139
-
140
- await this.coordinator.stop();
141
- this.resolveShutdown?.();
142
- this.resolveShutdown = null;
143
- }
144
- }
@@ -1,98 +0,0 @@
1
- import type { BuildResult, Message } from 'esbuild';
2
- import { emitDiagnostic } from '../core/diagnostics.js';
3
- import type { DiagnosticEvent } from '../core/diagnostics.js';
4
-
5
- export interface WatchReporterOptions {
6
- readonly verbose: boolean;
7
- }
8
-
9
- export interface SerializedMessage {
10
- readonly text: string;
11
- readonly location?: {
12
- readonly file?: string;
13
- readonly line?: number;
14
- readonly column?: number;
15
- };
16
- }
17
-
18
- export class WatchReporter {
19
- private readonly verbose: boolean;
20
-
21
- public constructor(options: WatchReporterOptions) {
22
- this.verbose = options.verbose;
23
- }
24
-
25
- public emit(event: DiagnosticEvent): void {
26
- emitDiagnostic(event);
27
- }
28
-
29
- public emitVerbose(event: DiagnosticEvent): void {
30
- if (!this.verbose) {
31
- return;
32
- }
33
-
34
- emitDiagnostic(event);
35
- }
36
-
37
- public emitJavaScriptStats(pageName: string, result: BuildResult, durationMs: number): void {
38
- if (!this.verbose) {
39
- return;
40
- }
41
-
42
- const stats = extractMetafileStats(result);
43
- const data: Record<string, unknown> = {
44
- page: pageName,
45
- durationMs: Number(durationMs.toFixed(1))
46
- };
47
-
48
- if (stats) {
49
- data.inputs = stats.inputs;
50
- data.outputs = stats.outputs;
51
- data.bytes = stats.bytes;
52
- }
53
-
54
- emitDiagnostic({
55
- code: 'frontend.watch.javascript.build.stats',
56
- kind: 'watch-daemon',
57
- stage: 'javascript',
58
- severity: 'info',
59
- message: `JavaScript rebuild stats for '${pageName}' (${durationMs.toFixed(1)}ms).`,
60
- data
61
- });
62
- }
63
- }
64
-
65
- export function serializeMessages(messages: readonly Message[]): SerializedMessage[] {
66
- return messages.map((message) => ({
67
- text: message.text,
68
- location: message.location
69
- ? {
70
- file: message.location.file,
71
- line: message.location.line,
72
- column: message.location.column
73
- }
74
- : undefined
75
- }));
76
- }
77
-
78
- function extractMetafileStats(result: BuildResult): MetafileStats | null {
79
- if (!result.metafile) {
80
- return null;
81
- }
82
-
83
- const inputs = Object.keys(result.metafile.inputs ?? {}).length;
84
- const outputsEntries = Object.entries(result.metafile.outputs ?? {});
85
- const bytes = outputsEntries.reduce((sum, [, output]) => sum + (output.bytes ?? 0), 0);
86
-
87
- return {
88
- inputs,
89
- outputs: outputsEntries.length,
90
- bytes
91
- };
92
- }
93
-
94
- interface MetafileStats {
95
- readonly inputs: number;
96
- readonly outputs: number;
97
- readonly bytes: number;
98
- }