@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,49 +1,50 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  export const frontendPathSchema = z.object({
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
- })
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
- htmlSecurity: z.boolean().default(true),
39
- imageOptimization: z.boolean().default(true),
40
- precompression: z.boolean().default(true)
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
- version: z.literal(1),
45
- paths: frontendPathSchema,
46
- features: frontendFeatureFlagsSchema
45
+ version: z.literal(1),
46
+ paths: frontendPathSchema,
47
+ features: frontendFeatureFlagsSchema,
47
48
  });
48
49
 
49
50
  export type FrontendConfigInput = z.infer<typeof frontendConfigSchema>;
@@ -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
- const config = buildConfig(workspaceRoot);
8
- await ensureWebstirDirectory(workspaceRoot);
9
- await writeConfigManifest({
10
- outputPath: resolveManifestPath(workspaceRoot),
11
- data: config
12
- });
13
- return config;
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
  }
@@ -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
- htmlSecurity: true,
9
- imageOptimization: true,
10
- precompression: true
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
- const srcRoot = path.join(workspaceRoot, FOLDERS.src);
15
- const frontendRoot = path.join(srcRoot, FOLDERS.frontend);
16
- const buildRoot = path.join(workspaceRoot, FOLDERS.build);
17
- const distRoot = path.join(workspaceRoot, FOLDERS.dist);
18
-
19
- const buildFrontend = path.join(buildRoot, FOLDERS.frontend);
20
- const distFrontend = path.join(distRoot, FOLDERS.frontend);
21
- const srcContentRoot = resolveContentRoot(workspaceRoot, frontendRoot);
22
-
23
- return {
24
- version: 1,
25
- paths: {
26
- workspace: workspaceRoot,
27
- src: {
28
- root: srcRoot,
29
- frontend: frontendRoot,
30
- app: path.join(frontendRoot, FOLDERS.app),
31
- pages: path.join(frontendRoot, FOLDERS.pages),
32
- content: srcContentRoot,
33
- images: path.join(frontendRoot, FOLDERS.images),
34
- fonts: path.join(frontendRoot, FOLDERS.fonts),
35
- media: path.join(frontendRoot, FOLDERS.media)
36
- },
37
- build: {
38
- root: buildRoot,
39
- frontend: buildFrontend,
40
- app: path.join(buildFrontend, FOLDERS.app),
41
- pages: path.join(buildFrontend, FOLDERS.pages),
42
- content: path.join(buildFrontend, FOLDERS.pages, 'docs'),
43
- images: path.join(buildFrontend, FOLDERS.images),
44
- fonts: path.join(buildFrontend, FOLDERS.fonts),
45
- media: path.join(buildFrontend, FOLDERS.media)
46
- },
47
- dist: {
48
- root: distRoot,
49
- frontend: distFrontend,
50
- app: path.join(distFrontend, FOLDERS.app),
51
- pages: path.join(distFrontend, FOLDERS.pages),
52
- content: path.join(distFrontend, FOLDERS.pages, 'docs'),
53
- images: path.join(distFrontend, FOLDERS.images),
54
- fonts: path.join(distFrontend, FOLDERS.fonts),
55
- media: path.join(distFrontend, FOLDERS.media)
56
- }
57
- },
58
- features: loadFeatureFlags(frontendRoot)
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
- const defaultContentRoot = path.join(frontendRoot, 'content');
64
- const configPath = path.join(frontendRoot, 'frontend.config.json');
65
- if (!fs.existsSync(configPath)) {
66
- return defaultContentRoot;
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
- try {
70
- const raw = fs.readFileSync(configPath, 'utf8');
71
- const parsed = JSON.parse(raw) as unknown;
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
- if (path.isAbsolute(trimmed)) {
88
- return trimmed;
89
- }
83
+ const trimmed = override.trim();
84
+ if (!trimmed) {
85
+ return defaultContentRoot;
86
+ }
90
87
 
91
- return path.join(workspaceRoot, trimmed);
92
- } catch (error) {
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
- if (!value || typeof value !== 'object') {
100
- return undefined;
101
- }
100
+ if (!value || typeof value !== 'object') {
101
+ return undefined;
102
+ }
102
103
 
103
- const container = value as Record<string, unknown>;
104
+ const container = value as Record<string, unknown>;
104
105
 
105
- if ('paths' in container && container.paths && typeof container.paths === 'object') {
106
- const pathsContainer = container.paths as Record<string, unknown>;
107
- if ('contentRoot' in pathsContainer) {
108
- return pathsContainer.contentRoot;
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
- if ('contentRoot' in container) {
113
- return container.contentRoot;
114
- }
113
+ if ('contentRoot' in container) {
114
+ return container.contentRoot;
115
+ }
115
116
 
116
- return undefined;
117
+ return undefined;
117
118
  }
118
119
 
119
120
  function loadFeatureFlags(frontendRoot: string): FrontendFeatureFlags {
120
- const configPath = path.join(frontendRoot, 'frontend.config.json');
121
- if (!fs.existsSync(configPath)) {
122
- return DEFAULT_FEATURE_FLAGS;
123
- }
124
-
125
- try {
126
- const raw = fs.readFileSync(configPath, 'utf8');
127
- const parsed = JSON.parse(raw) as unknown;
128
- const overridesSource = extractOverrideSource(parsed);
129
- const overrides = frontendFeatureFlagsSchema.parse(overridesSource);
130
- return {
131
- htmlSecurity: overrides.htmlSecurity,
132
- imageOptimization: overrides.imageOptimization,
133
- precompression: overrides.precompression
134
- };
135
- } catch (error) {
136
- const message = error instanceof Error ? error.message : String(error);
137
- throw new Error(`Failed to read frontend feature flags from ${configPath}: ${message}`);
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
- if (value && typeof value === 'object' && 'features' in (value as Record<string, unknown>)) {
143
- const container = (value as Record<string, unknown>).features;
144
- if (container && typeof container === 'object') {
145
- return container as Record<string, unknown>;
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
- return (value && typeof value === 'object') ? value as Record<string, unknown> : {};
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
- readonly name?: string;
5
- readonly path?: string;
6
- readonly renderMode?: RenderMode;
7
- readonly staticPaths?: readonly string[];
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
- readonly renderMode?: unknown;
12
- readonly staticPaths?: unknown;
13
- readonly ssg?: unknown;
11
+ readonly renderMode?: unknown;
12
+ readonly staticPaths?: unknown;
13
+ readonly ssg?: unknown;
14
14
  }
15
15
 
16
16
  export interface WorkspaceModuleConfig {
17
- readonly views?: readonly WorkspaceModuleView[];
18
- readonly routes?: readonly WorkspaceModuleRouteGuard[];
17
+ readonly views?: readonly WorkspaceModuleView[];
18
+ readonly routes?: readonly WorkspaceModuleRouteGuard[];
19
19
  }
20
20
 
21
21
  export interface WorkspacePackageJson {
22
- readonly name?: string;
23
- readonly webstir?: {
24
- readonly mode?: string;
25
- readonly moduleManifest?: WorkspaceModuleConfig;
26
- };
22
+ readonly name?: string;
23
+ readonly webstir?: {
24
+ readonly mode?: string;
25
+ readonly moduleManifest?: WorkspaceModuleConfig;
26
+ };
27
27
  }
@@ -1,73 +1,73 @@
1
1
  export const FOLDERS = {
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'
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
- packageJson: 'package.json',
28
- packageLockJson: 'package-lock.json',
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'
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
- 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'
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
- htmlAppTemplate: 'app.html'
72
+ htmlAppTemplate: 'app.html',
73
73
  } as const;
@@ -1,40 +1,40 @@
1
1
  export type DiagnosticSeverity = 'info' | 'warning' | 'error';
2
2
 
3
3
  export interface DiagnosticEvent {
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;
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
- readonly type: 'diagnostic';
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
- const payload: DiagnosticPayload = {
21
- type: 'diagnostic',
22
- ...event
23
- };
20
+ const payload: DiagnosticPayload = {
21
+ type: 'diagnostic',
22
+ ...event,
23
+ };
24
24
 
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
- }
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
- const serialized = JSON.stringify(payload);
39
- console.log(`${STRUCTURED_DIAGNOSTIC_PREFIX}${serialized}`);
38
+ const serialized = JSON.stringify(payload);
39
+ console.log(`${STRUCTURED_DIAGNOSTIC_PREFIX}${serialized}`);
40
40
  }