@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
package/src/config/schema.ts
CHANGED
|
@@ -1,49 +1,50 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
export const frontendPathSchema = z.object({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
4
|
+
workspace: z.string(),
|
|
5
|
+
src: z.object({
|
|
6
|
+
root: z.string(),
|
|
7
|
+
frontend: z.string(),
|
|
8
|
+
app: z.string(),
|
|
9
|
+
pages: z.string(),
|
|
10
|
+
content: z.string(),
|
|
11
|
+
images: z.string(),
|
|
12
|
+
fonts: z.string(),
|
|
13
|
+
media: z.string(),
|
|
14
|
+
}),
|
|
15
|
+
build: z.object({
|
|
16
|
+
root: z.string(),
|
|
17
|
+
frontend: z.string(),
|
|
18
|
+
app: z.string(),
|
|
19
|
+
pages: z.string(),
|
|
20
|
+
content: z.string(),
|
|
21
|
+
images: z.string(),
|
|
22
|
+
fonts: z.string(),
|
|
23
|
+
media: z.string(),
|
|
24
|
+
}),
|
|
25
|
+
dist: z.object({
|
|
26
|
+
root: z.string(),
|
|
27
|
+
frontend: z.string(),
|
|
28
|
+
app: z.string(),
|
|
29
|
+
pages: z.string(),
|
|
30
|
+
content: z.string(),
|
|
31
|
+
images: z.string(),
|
|
32
|
+
fonts: z.string(),
|
|
33
|
+
media: z.string(),
|
|
34
|
+
}),
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
export const frontendFeatureFlagsSchema = z.object({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
htmlSecurity: z.boolean().default(true),
|
|
39
|
+
externalResourceIntegrity: z.boolean().default(false),
|
|
40
|
+
imageOptimization: z.boolean().default(true),
|
|
41
|
+
precompression: z.boolean().default(true),
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
export const frontendConfigSchema = z.object({
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
version: z.literal(1),
|
|
46
|
+
paths: frontendPathSchema,
|
|
47
|
+
features: frontendFeatureFlagsSchema,
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
export type FrontendConfigInput = z.infer<typeof frontendConfigSchema>;
|
package/src/config/setup.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { ensureWebstirDirectory, resolveManifestPath } from './paths.js';
|
|
|
4
4
|
import type { FrontendConfig } from '../types.js';
|
|
5
5
|
|
|
6
6
|
export async function prepareWorkspaceConfig(workspaceRoot: string): Promise<FrontendConfig> {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
const config = buildConfig(workspaceRoot);
|
|
8
|
+
await ensureWebstirDirectory(workspaceRoot);
|
|
9
|
+
await writeConfigManifest({
|
|
10
|
+
outputPath: resolveManifestPath(workspaceRoot),
|
|
11
|
+
data: config,
|
|
12
|
+
});
|
|
13
|
+
return config;
|
|
14
14
|
}
|
package/src/config/workspace.ts
CHANGED
|
@@ -1,150 +1,152 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'path';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import type { FrontendConfig, FrontendFeatureFlags } from '../types.js';
|
|
4
4
|
import { FOLDERS } from '../core/constants.js';
|
|
5
5
|
import { frontendFeatureFlagsSchema } from './schema.js';
|
|
6
6
|
|
|
7
7
|
const DEFAULT_FEATURE_FLAGS: FrontendFeatureFlags = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
htmlSecurity: true,
|
|
9
|
+
externalResourceIntegrity: false,
|
|
10
|
+
imageOptimization: true,
|
|
11
|
+
precompression: true,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export function buildConfig(workspaceRoot: string): FrontendConfig {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
15
|
+
const srcRoot = path.join(workspaceRoot, FOLDERS.src);
|
|
16
|
+
const frontendRoot = path.join(srcRoot, FOLDERS.frontend);
|
|
17
|
+
const buildRoot = path.join(workspaceRoot, FOLDERS.build);
|
|
18
|
+
const distRoot = path.join(workspaceRoot, FOLDERS.dist);
|
|
19
|
+
|
|
20
|
+
const buildFrontend = path.join(buildRoot, FOLDERS.frontend);
|
|
21
|
+
const distFrontend = path.join(distRoot, FOLDERS.frontend);
|
|
22
|
+
const srcContentRoot = resolveContentRoot(workspaceRoot, frontendRoot);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
version: 1,
|
|
26
|
+
paths: {
|
|
27
|
+
workspace: workspaceRoot,
|
|
28
|
+
src: {
|
|
29
|
+
root: srcRoot,
|
|
30
|
+
frontend: frontendRoot,
|
|
31
|
+
app: path.join(frontendRoot, FOLDERS.app),
|
|
32
|
+
pages: path.join(frontendRoot, FOLDERS.pages),
|
|
33
|
+
content: srcContentRoot,
|
|
34
|
+
images: path.join(frontendRoot, FOLDERS.images),
|
|
35
|
+
fonts: path.join(frontendRoot, FOLDERS.fonts),
|
|
36
|
+
media: path.join(frontendRoot, FOLDERS.media),
|
|
37
|
+
},
|
|
38
|
+
build: {
|
|
39
|
+
root: buildRoot,
|
|
40
|
+
frontend: buildFrontend,
|
|
41
|
+
app: path.join(buildFrontend, FOLDERS.app),
|
|
42
|
+
pages: path.join(buildFrontend, FOLDERS.pages),
|
|
43
|
+
content: path.join(buildFrontend, FOLDERS.pages, 'docs'),
|
|
44
|
+
images: path.join(buildFrontend, FOLDERS.images),
|
|
45
|
+
fonts: path.join(buildFrontend, FOLDERS.fonts),
|
|
46
|
+
media: path.join(buildFrontend, FOLDERS.media),
|
|
47
|
+
},
|
|
48
|
+
dist: {
|
|
49
|
+
root: distRoot,
|
|
50
|
+
frontend: distFrontend,
|
|
51
|
+
app: path.join(distFrontend, FOLDERS.app),
|
|
52
|
+
pages: path.join(distFrontend, FOLDERS.pages),
|
|
53
|
+
content: path.join(distFrontend, FOLDERS.pages, 'docs'),
|
|
54
|
+
images: path.join(distFrontend, FOLDERS.images),
|
|
55
|
+
fonts: path.join(distFrontend, FOLDERS.fonts),
|
|
56
|
+
media: path.join(distFrontend, FOLDERS.media),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
features: loadFeatureFlags(frontendRoot),
|
|
60
|
+
};
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
function resolveContentRoot(workspaceRoot: string, frontendRoot: string): string {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const defaultContentRoot = path.join(frontendRoot, 'content');
|
|
65
|
+
const configPath = path.join(frontendRoot, 'frontend.config.json');
|
|
66
|
+
if (!fs.existsSync(configPath)) {
|
|
67
|
+
return defaultContentRoot;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
72
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
73
|
+
const override = extractContentRoot(parsed);
|
|
74
|
+
|
|
75
|
+
if (override === undefined) {
|
|
76
|
+
return defaultContentRoot;
|
|
67
77
|
}
|
|
68
78
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const override = extractContentRoot(parsed);
|
|
73
|
-
|
|
74
|
-
if (override === undefined) {
|
|
75
|
-
return defaultContentRoot;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (typeof override !== 'string') {
|
|
79
|
-
throw new Error('Expected contentRoot to be a string when specified.');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const trimmed = override.trim();
|
|
83
|
-
if (!trimmed) {
|
|
84
|
-
return defaultContentRoot;
|
|
85
|
-
}
|
|
79
|
+
if (typeof override !== 'string') {
|
|
80
|
+
throw new Error('Expected contentRoot to be a string when specified.');
|
|
81
|
+
}
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
const trimmed = override.trim();
|
|
84
|
+
if (!trimmed) {
|
|
85
|
+
return defaultContentRoot;
|
|
86
|
+
}
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
-
throw new Error(`Failed to read frontend content root from ${configPath}: ${message}`);
|
|
88
|
+
if (path.isAbsolute(trimmed)) {
|
|
89
|
+
return trimmed;
|
|
95
90
|
}
|
|
91
|
+
|
|
92
|
+
return path.join(workspaceRoot, trimmed);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
95
|
+
throw new Error(`Failed to read frontend content root from ${configPath}: ${message}`);
|
|
96
|
+
}
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
function extractContentRoot(value: unknown): unknown {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
if (!value || typeof value !== 'object') {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
const container = value as Record<string, unknown>;
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
106
|
+
if ('paths' in container && container.paths && typeof container.paths === 'object') {
|
|
107
|
+
const pathsContainer = container.paths as Record<string, unknown>;
|
|
108
|
+
if ('contentRoot' in pathsContainer) {
|
|
109
|
+
return pathsContainer.contentRoot;
|
|
110
110
|
}
|
|
111
|
+
}
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
if ('contentRoot' in container) {
|
|
114
|
+
return container.contentRoot;
|
|
115
|
+
}
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
return undefined;
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
function loadFeatureFlags(frontendRoot: string): FrontendFeatureFlags {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
121
|
+
const configPath = path.join(frontendRoot, 'frontend.config.json');
|
|
122
|
+
if (!fs.existsSync(configPath)) {
|
|
123
|
+
return DEFAULT_FEATURE_FLAGS;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
128
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
129
|
+
const overridesSource = extractOverrideSource(parsed);
|
|
130
|
+
const overrides = frontendFeatureFlagsSchema.parse(overridesSource);
|
|
131
|
+
return {
|
|
132
|
+
htmlSecurity: overrides.htmlSecurity,
|
|
133
|
+
externalResourceIntegrity: overrides.externalResourceIntegrity,
|
|
134
|
+
imageOptimization: overrides.imageOptimization,
|
|
135
|
+
precompression: overrides.precompression,
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {
|
|
138
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
139
|
+
throw new Error(`Failed to read frontend feature flags from ${configPath}: ${message}`);
|
|
140
|
+
}
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
function extractOverrideSource(value: unknown): Record<string, unknown> {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
144
|
+
if (value && typeof value === 'object' && 'features' in (value as Record<string, unknown>)) {
|
|
145
|
+
const container = (value as Record<string, unknown>).features;
|
|
146
|
+
if (container && typeof container === 'object') {
|
|
147
|
+
return container as Record<string, unknown>;
|
|
147
148
|
}
|
|
149
|
+
}
|
|
148
150
|
|
|
149
|
-
|
|
151
|
+
return value && typeof value === 'object' ? (value as Record<string, unknown>) : {};
|
|
150
152
|
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
export type RenderMode = 'ssg' | 'ssr' | 'spa';
|
|
2
2
|
|
|
3
3
|
export interface WorkspaceModuleView {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly path?: string;
|
|
6
|
+
readonly renderMode?: RenderMode;
|
|
7
|
+
readonly staticPaths?: readonly string[];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface WorkspaceModuleRouteGuard {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
readonly renderMode?: unknown;
|
|
12
|
+
readonly staticPaths?: unknown;
|
|
13
|
+
readonly ssg?: unknown;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface WorkspaceModuleConfig {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
readonly views?: readonly WorkspaceModuleView[];
|
|
18
|
+
readonly routes?: readonly WorkspaceModuleRouteGuard[];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface WorkspacePackageJson {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
readonly name?: string;
|
|
23
|
+
readonly webstir?: {
|
|
24
|
+
readonly mode?: string;
|
|
25
|
+
readonly moduleManifest?: WorkspaceModuleConfig;
|
|
26
|
+
};
|
|
27
27
|
}
|
package/src/core/constants.ts
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
1
|
export const FOLDERS = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
src: 'src',
|
|
3
|
+
build: 'build',
|
|
4
|
+
dist: 'dist',
|
|
5
|
+
webstir: '.webstir',
|
|
6
|
+
tests: 'tests',
|
|
7
|
+
frontend: 'frontend',
|
|
8
|
+
backend: 'backend',
|
|
9
|
+
shared: 'shared',
|
|
10
|
+
types: 'types',
|
|
11
|
+
app: 'app',
|
|
12
|
+
pages: 'pages',
|
|
13
|
+
styles: 'styles',
|
|
14
|
+
scripts: 'scripts',
|
|
15
|
+
images: 'images',
|
|
16
|
+
fonts: 'fonts',
|
|
17
|
+
media: 'media',
|
|
18
|
+
chunks: 'chunks',
|
|
19
|
+
home: 'home',
|
|
20
|
+
nodeModules: 'node_modules',
|
|
21
|
+
seed: 'seed',
|
|
22
|
+
demo: 'demo',
|
|
23
|
+
temp: 'temp',
|
|
24
24
|
} as const;
|
|
25
25
|
|
|
26
26
|
export const FILES = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
packageJson: 'package.json',
|
|
28
|
+
bunLock: 'bun.lock',
|
|
29
|
+
tsBuildInfo: '.tsbuildinfo',
|
|
30
|
+
baseTsConfigJson: 'base.tsconfig.json',
|
|
31
|
+
manifestJson: 'manifest.json',
|
|
32
|
+
test: '.test',
|
|
33
|
+
index: 'index',
|
|
34
|
+
indexHtml: 'index.html',
|
|
35
|
+
refreshJs: 'refresh.js',
|
|
36
|
+
hmrJs: 'hmr.js',
|
|
37
|
+
robotsTxt: 'robots.txt',
|
|
38
38
|
} as const;
|
|
39
39
|
|
|
40
40
|
export const EXTENSIONS = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
41
|
+
html: '.html',
|
|
42
|
+
css: '.css',
|
|
43
|
+
br: '.br',
|
|
44
|
+
gz: '.gz',
|
|
45
|
+
dts: '.d.ts',
|
|
46
|
+
ts: '.ts',
|
|
47
|
+
js: '.js',
|
|
48
|
+
map: '.map',
|
|
49
|
+
png: '.png',
|
|
50
|
+
jpg: '.jpg',
|
|
51
|
+
jpeg: '.jpeg',
|
|
52
|
+
gif: '.gif',
|
|
53
|
+
svg: '.svg',
|
|
54
|
+
webp: '.webp',
|
|
55
|
+
avif: '.avif',
|
|
56
|
+
ico: '.ico',
|
|
57
|
+
woff: '.woff',
|
|
58
|
+
woff2: '.woff2',
|
|
59
|
+
ttf: '.ttf',
|
|
60
|
+
otf: '.otf',
|
|
61
|
+
eot: '.eot',
|
|
62
|
+
mp3: '.mp3',
|
|
63
|
+
m4a: '.m4a',
|
|
64
|
+
wav: '.wav',
|
|
65
|
+
ogg: '.ogg',
|
|
66
|
+
mp4: '.mp4',
|
|
67
|
+
webm: '.webm',
|
|
68
|
+
mov: '.mov',
|
|
69
69
|
} as const;
|
|
70
70
|
|
|
71
71
|
export const FILE_NAMES = {
|
|
72
|
-
|
|
72
|
+
htmlAppTemplate: 'app.html',
|
|
73
73
|
} as const;
|
package/src/core/diagnostics.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
export type DiagnosticSeverity = 'info' | 'warning' | 'error';
|
|
2
2
|
|
|
3
3
|
export interface DiagnosticEvent {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly kind: string;
|
|
6
|
+
readonly stage: string;
|
|
7
|
+
readonly severity: DiagnosticSeverity;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly data?: Record<string, unknown>;
|
|
10
|
+
readonly suggestion?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface DiagnosticPayload extends DiagnosticEvent {
|
|
14
|
-
|
|
14
|
+
readonly type: 'diagnostic';
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export const STRUCTURED_DIAGNOSTIC_PREFIX = 'WEBSTIR_DIAGNOSTIC ';
|
|
18
18
|
|
|
19
19
|
export function emitDiagnostic(event: DiagnosticEvent): void {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const payload: DiagnosticPayload = {
|
|
21
|
+
type: 'diagnostic',
|
|
22
|
+
...event,
|
|
23
|
+
};
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
const logMessage = `[webstir-frontend][${event.code}] ${event.message}`;
|
|
26
|
+
switch (event.severity) {
|
|
27
|
+
case 'error':
|
|
28
|
+
console.error(logMessage);
|
|
29
|
+
break;
|
|
30
|
+
case 'warning':
|
|
31
|
+
console.warn(logMessage);
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
console.info(logMessage);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const serialized = JSON.stringify(payload);
|
|
39
|
+
console.log(`${STRUCTURED_DIAGNOSTIC_PREFIX}${serialized}`);
|
|
40
40
|
}
|