@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
package/src/provider.ts CHANGED
@@ -3,15 +3,14 @@ import { readdir } from 'node:fs/promises';
3
3
  import fs from 'node:fs';
4
4
  import { createRequire } from 'node:module';
5
5
 
6
- import { glob } from 'glob';
7
6
  import type {
8
- ModuleAsset,
9
- ModuleArtifact,
10
- ModuleBuildOptions,
11
- ModuleBuildResult,
12
- ModuleDiagnostic,
13
- ModuleProvider,
14
- ResolvedModuleWorkspace
7
+ ModuleAsset,
8
+ ModuleArtifact,
9
+ ModuleBuildOptions,
10
+ ModuleBuildResult,
11
+ ModuleDiagnostic,
12
+ ModuleProvider,
13
+ ResolvedModuleWorkspace,
15
14
  } from '@webstir-io/module-contract';
16
15
 
17
16
  import { runPipeline } from './pipeline.js';
@@ -20,230 +19,239 @@ import { prepareWorkspaceConfig } from './config/setup.js';
20
19
  import type { FrontendConfig } from './types.js';
21
20
  import { FOLDERS } from './core/constants.js';
22
21
  import { pathExists, readJson, remove } from './utils/fs.js';
22
+ import { scanGlob } from './utils/glob.js';
23
23
  import { applySsgRouting, assertNoSsgRoutes, generateSsgViewData } from './modes/ssg/index.js';
24
24
 
25
25
  interface PackageJson {
26
- readonly name: string;
27
- readonly version: string;
28
- readonly engines?: {
29
- readonly node?: string;
30
- };
26
+ readonly name: string;
27
+ readonly version: string;
28
+ readonly engines?: {
29
+ readonly node?: string;
30
+ readonly bun?: string;
31
+ };
31
32
  }
32
33
 
33
34
  const require = createRequire(import.meta.url);
34
35
  const pkg = require('../package.json') as PackageJson;
35
36
 
36
37
  function resolveWorkspacePaths(workspaceRoot: string): ResolvedModuleWorkspace {
37
- return {
38
- sourceRoot: path.join(workspaceRoot, 'src', 'frontend'),
39
- buildRoot: path.join(workspaceRoot, 'build', 'frontend'),
40
- testsRoot: path.join(workspaceRoot, 'src', 'frontend', 'tests')
41
- };
38
+ return {
39
+ sourceRoot: path.join(workspaceRoot, 'src', 'frontend'),
40
+ buildRoot: path.join(workspaceRoot, 'build', 'frontend'),
41
+ testsRoot: path.join(workspaceRoot, 'src', 'frontend', 'tests'),
42
+ };
42
43
  }
43
44
 
44
45
  async function buildModule(options: ModuleBuildOptions): Promise<ModuleBuildResult> {
45
- const config = await prepareWorkspaceConfig(options.workspaceRoot);
46
- const mode = normalizeMode(options.env?.WEBSTIR_MODULE_MODE);
47
- const workspaceMode = await readWorkspaceMode(options.workspaceRoot);
48
- const frontendMode = normalizeFrontendMode(options.env?.WEBSTIR_FRONTEND_MODE);
49
- const shouldRunSsgPublish =
50
- mode === 'publish' && (frontendMode === 'ssg' || (frontendMode === undefined && workspaceMode.mode === 'ssg'));
51
- const publishConfig = shouldRunSsgPublish ? applySsgPublishLayout(config) : config;
52
-
53
- if (shouldRunSsgPublish) {
54
- await assertNoSsgRoutes(config.paths.workspace);
55
- }
56
- await runPipeline(publishConfig, mode, { changedFile: undefined, enable: workspaceMode.enable });
46
+ const config = await prepareWorkspaceConfig(options.workspaceRoot);
47
+ const mode = normalizeMode(options.env?.WEBSTIR_MODULE_MODE);
48
+ const workspaceMode = await readWorkspaceMode(options.workspaceRoot);
49
+ const frontendMode = normalizeFrontendMode(options.env?.WEBSTIR_FRONTEND_MODE);
50
+ const shouldRunSsgPublish =
51
+ mode === 'publish' &&
52
+ (frontendMode === 'ssg' || (frontendMode === undefined && workspaceMode.mode === 'ssg'));
53
+ const publishConfig = shouldRunSsgPublish ? applySsgPublishLayout(config) : config;
54
+
55
+ if (shouldRunSsgPublish) {
56
+ await assertNoSsgRoutes(config.paths.workspace);
57
+ }
58
+ await runPipeline(publishConfig, mode, {
59
+ changedFile: undefined,
60
+ enable: workspaceMode.enable,
61
+ env: {
62
+ ...process.env,
63
+ ...options.env,
64
+ },
65
+ });
57
66
 
58
- if (shouldRunSsgPublish) {
59
- await generateSsgViewData(publishConfig);
60
- await applySsgRouting(publishConfig);
61
- await removeLegacyPagesFolder(publishConfig);
62
- }
67
+ if (shouldRunSsgPublish) {
68
+ await generateSsgViewData(publishConfig);
69
+ await applySsgRouting(publishConfig);
70
+ await removeLegacyPagesFolder(publishConfig);
71
+ }
63
72
 
64
- const artifacts = await collectArtifacts(config);
65
- const manifest = createManifest(config, artifacts, workspaceMode.mode, workspaceMode.isSsg);
73
+ const artifacts = await collectArtifacts(config);
74
+ const manifest = createManifest(config, artifacts, workspaceMode.mode, workspaceMode.isSsg);
66
75
 
67
- return {
68
- artifacts,
69
- manifest
70
- };
76
+ return {
77
+ artifacts,
78
+ manifest,
79
+ };
71
80
  }
72
81
 
73
82
  function applySsgPublishLayout(config: FrontendConfig): FrontendConfig {
74
- const distFrontend = config.paths.dist.frontend;
75
- const distPages = distFrontend;
76
- const distContent = path.join(distFrontend, 'docs');
77
-
78
- return {
79
- ...config,
80
- paths: {
81
- ...config.paths,
82
- dist: {
83
- ...config.paths.dist,
84
- pages: distPages,
85
- content: distContent
86
- }
87
- }
88
- };
83
+ const distFrontend = config.paths.dist.frontend;
84
+ const distPages = distFrontend;
85
+ const distContent = path.join(distFrontend, 'docs');
86
+
87
+ return {
88
+ ...config,
89
+ paths: {
90
+ ...config.paths,
91
+ dist: {
92
+ ...config.paths.dist,
93
+ pages: distPages,
94
+ content: distContent,
95
+ },
96
+ },
97
+ };
89
98
  }
90
99
 
91
100
  async function removeLegacyPagesFolder(config: FrontendConfig): Promise<void> {
92
- const legacyPagesRoot = path.join(config.paths.dist.frontend, FOLDERS.pages);
93
- if (legacyPagesRoot === config.paths.dist.pages) {
94
- return;
95
- }
101
+ const legacyPagesRoot = path.join(config.paths.dist.frontend, FOLDERS.pages);
102
+ if (legacyPagesRoot === config.paths.dist.pages) {
103
+ return;
104
+ }
96
105
 
97
- if (!(await pathExists(legacyPagesRoot))) {
98
- return;
99
- }
106
+ if (!(await pathExists(legacyPagesRoot))) {
107
+ return;
108
+ }
100
109
 
101
- const entries = await readdir(legacyPagesRoot);
102
- if (entries.length > 0) {
103
- return;
104
- }
110
+ const entries = await readdir(legacyPagesRoot);
111
+ if (entries.length > 0) {
112
+ return;
113
+ }
105
114
 
106
- await remove(legacyPagesRoot);
115
+ await remove(legacyPagesRoot);
107
116
  }
108
117
 
109
118
  function normalizeMode(rawMode: unknown): PipelineMode {
110
- if (typeof rawMode !== 'string') {
111
- return 'build';
112
- }
119
+ if (typeof rawMode !== 'string') {
120
+ return 'build';
121
+ }
113
122
 
114
- return rawMode.toLowerCase() === 'publish' ? 'publish' : 'build';
123
+ return rawMode.toLowerCase() === 'publish' ? 'publish' : 'build';
115
124
  }
116
125
 
117
126
  async function getScaffoldAssets(): Promise<readonly ModuleAsset[]> {
118
- return [];
127
+ return [];
119
128
  }
120
129
 
121
130
  async function collectArtifacts(config: FrontendConfig): Promise<ModuleArtifact[]> {
122
- const buildRoot = config.paths.build.frontend;
123
- const matches = await glob('**/*', {
124
- cwd: buildRoot,
125
- nodir: true,
126
- dot: false
127
- });
128
-
129
- return matches.map<ModuleArtifact>((relative) => {
130
- const absolutePath = path.join(buildRoot, relative);
131
- const ext = path.extname(relative).toLowerCase();
132
- const artifactType = ext === '.js' || ext === '.mjs' ? 'bundle' : 'asset';
133
-
134
- return {
135
- path: absolutePath,
136
- type: artifactType
137
- };
138
- });
131
+ const buildRoot = config.paths.build.frontend;
132
+ const matches = await scanGlob('**/*', {
133
+ cwd: buildRoot,
134
+ dot: false,
135
+ });
136
+
137
+ return matches.map<ModuleArtifact>((relative) => {
138
+ const absolutePath = path.join(buildRoot, relative);
139
+ const ext = path.extname(relative).toLowerCase();
140
+ const artifactType = ext === '.js' || ext === '.mjs' ? 'bundle' : 'asset';
141
+
142
+ return {
143
+ path: absolutePath,
144
+ type: artifactType,
145
+ };
146
+ });
139
147
  }
140
148
 
141
149
  interface WorkspaceEnableFlags {
142
- readonly spa?: boolean;
143
- readonly clientNav?: boolean;
144
- readonly backend?: boolean;
145
- readonly search?: boolean;
150
+ readonly spa?: boolean;
151
+ readonly clientNav?: boolean;
152
+ readonly backend?: boolean;
153
+ readonly search?: boolean;
146
154
  }
147
155
 
148
156
  interface WorkspacePackageJson {
149
- readonly webstir?: {
150
- readonly mode?: string;
151
- readonly enable?: WorkspaceEnableFlags;
152
- readonly moduleManifest?: {
153
- readonly views?: ReadonlyArray<{
154
- readonly renderMode?: string;
155
- }>;
156
- };
157
+ readonly webstir?: {
158
+ readonly mode?: string;
159
+ readonly enable?: WorkspaceEnableFlags;
160
+ readonly moduleManifest?: {
161
+ readonly views?: ReadonlyArray<{
162
+ readonly renderMode?: string;
163
+ }>;
157
164
  };
165
+ };
158
166
  }
159
167
 
160
168
  function createManifest(
161
- config: FrontendConfig,
162
- assets: readonly ModuleArtifact[],
163
- workspaceMode?: string,
164
- isSsgWorkspace?: boolean
169
+ config: FrontendConfig,
170
+ assets: readonly ModuleArtifact[],
171
+ workspaceMode?: string,
172
+ isSsgWorkspace?: boolean,
165
173
  ) {
166
- const entryPoints: string[] = [];
167
- const staticAssets: string[] = [];
168
- const diagnostics: ModuleDiagnostic[] = [];
169
-
170
- const normalizedMode = workspaceMode?.toLowerCase();
171
- const isSsg = isSsgWorkspace || normalizedMode === 'ssg';
172
-
173
- for (const asset of assets) {
174
- const relativePath = path.relative(config.paths.build.frontend, asset.path);
175
- const ext = path.extname(relativePath).toLowerCase();
176
-
177
- if (ext === '.js' || ext === '.mjs') {
178
- entryPoints.push(relativePath);
179
- } else if (ext) {
180
- staticAssets.push(relativePath);
181
- }
182
- }
174
+ const entryPoints: string[] = [];
175
+ const staticAssets: string[] = [];
176
+ const diagnostics: ModuleDiagnostic[] = [];
177
+
178
+ const normalizedMode = workspaceMode?.toLowerCase();
179
+ const isSsg = isSsgWorkspace || normalizedMode === 'ssg';
183
180
 
184
- if (entryPoints.length === 0) {
185
- const fallback = path.join(config.paths.build.app, 'index.js');
186
- if (fs.existsSync(fallback)) {
187
- entryPoints.push(path.relative(config.paths.build.frontend, fallback));
188
- } else if (!isSsg) {
189
- diagnostics.push({
190
- severity: 'warn',
191
- message: 'No JavaScript entry points found under build/frontend.'
192
- });
193
- }
181
+ for (const asset of assets) {
182
+ const relativePath = path.relative(config.paths.build.frontend, asset.path);
183
+ const ext = path.extname(relativePath).toLowerCase();
184
+
185
+ if (ext === '.js' || ext === '.mjs') {
186
+ entryPoints.push(relativePath);
187
+ } else if (ext) {
188
+ staticAssets.push(relativePath);
189
+ }
190
+ }
191
+
192
+ if (entryPoints.length === 0) {
193
+ const fallback = path.join(config.paths.build.app, 'index.js');
194
+ if (fs.existsSync(fallback)) {
195
+ entryPoints.push(path.relative(config.paths.build.frontend, fallback));
196
+ } else if (!isSsg) {
197
+ diagnostics.push({
198
+ severity: 'warn',
199
+ message: 'No JavaScript entry points found under build/frontend.',
200
+ });
194
201
  }
202
+ }
195
203
 
196
- return {
197
- entryPoints,
198
- staticAssets,
199
- diagnostics
200
- };
204
+ return {
205
+ entryPoints,
206
+ staticAssets,
207
+ diagnostics,
208
+ };
201
209
  }
202
210
 
203
- async function readWorkspaceMode(workspaceRoot: string): Promise<{ mode?: string; isSsg: boolean; enable?: WorkspaceEnableFlags }> {
204
- const pkgPath = path.join(workspaceRoot, 'package.json');
205
- const pkg = await readJson<WorkspacePackageJson>(pkgPath);
206
- const mode = pkg?.webstir?.mode;
207
- const normalizedMode = typeof mode === 'string' ? mode.toLowerCase() : undefined;
208
- const views = pkg?.webstir?.moduleManifest?.views;
209
- const hasSsgView = Array.isArray(views) && views.some(view => view.renderMode?.toLowerCase() === 'ssg');
210
- return {
211
- mode,
212
- isSsg: normalizedMode === 'ssg' || hasSsgView,
213
- enable: pkg?.webstir?.enable
214
- };
211
+ async function readWorkspaceMode(
212
+ workspaceRoot: string,
213
+ ): Promise<{ mode?: string; isSsg: boolean; enable?: WorkspaceEnableFlags }> {
214
+ const pkgPath = path.join(workspaceRoot, 'package.json');
215
+ const pkg = await readJson<WorkspacePackageJson>(pkgPath);
216
+ const mode = pkg?.webstir?.mode;
217
+ const normalizedMode = typeof mode === 'string' ? mode.toLowerCase() : undefined;
218
+ const views = pkg?.webstir?.moduleManifest?.views;
219
+ const hasSsgView =
220
+ Array.isArray(views) && views.some((view) => view.renderMode?.toLowerCase() === 'ssg');
221
+ return {
222
+ mode,
223
+ isSsg: normalizedMode === 'ssg' || hasSsgView,
224
+ enable: pkg?.webstir?.enable,
225
+ };
215
226
  }
216
227
 
217
228
  function normalizeFrontendMode(value: unknown): 'bundle' | 'ssg' | undefined {
218
- if (typeof value !== 'string') {
219
- return undefined;
220
- }
229
+ if (typeof value !== 'string') {
230
+ return undefined;
231
+ }
221
232
 
222
- const normalized = value.trim().toLowerCase();
223
- return normalized === 'ssg'
224
- ? 'ssg'
225
- : normalized === 'bundle'
226
- ? 'bundle'
227
- : undefined;
233
+ const normalized = value.trim().toLowerCase();
234
+ return normalized === 'ssg' ? 'ssg' : normalized === 'bundle' ? 'bundle' : undefined;
228
235
  }
229
236
 
230
237
  export const frontendProvider: ModuleProvider = {
231
- metadata: {
232
- id: pkg.name ?? '@webstir-io/webstir-frontend',
233
- kind: 'frontend',
234
- version: pkg.version ?? '0.0.0',
235
- compatibility: {
236
- minCliVersion: '0.1.0',
237
- nodeRange: pkg.engines?.node ?? '>=20.18.1'
238
- }
239
- },
240
- resolveWorkspace(options) {
241
- return resolveWorkspacePaths(options.workspaceRoot);
238
+ metadata: {
239
+ id: pkg.name ?? '@webstir-io/webstir-frontend',
240
+ kind: 'frontend',
241
+ version: pkg.version ?? '0.0.0',
242
+ compatibility: {
243
+ minCliVersion: '0.1.0',
244
+ nodeRange: pkg.engines?.node ?? '>=20.18.1',
245
+ ...(pkg.engines?.bun ? { notes: `Requires Bun ${pkg.engines.bun} at runtime.` } : {}),
242
246
  },
243
- async build(options) {
244
- return await buildModule(options);
245
- },
246
- async getScaffoldAssets() {
247
- return await getScaffoldAssets();
248
- }
247
+ },
248
+ resolveWorkspace(options) {
249
+ return resolveWorkspacePaths(options.workspaceRoot);
250
+ },
251
+ async build(options) {
252
+ return await buildModule(options);
253
+ },
254
+ async getScaffoldAssets() {
255
+ return await getScaffoldAssets();
256
+ },
249
257
  };