@blinkk/root 1.0.0-alpha.14 → 1.0.0-alpha.15

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/dist/cli.js CHANGED
@@ -4,14 +4,19 @@ import {
4
4
  } from "./chunk-ZB7R6ZOY.js";
5
5
 
6
6
  // src/cli/commands/dev.ts
7
- import path4 from "node:path";
7
+ import path5 from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { default as express } from "express";
10
10
  import { createServer as createViteServer } from "vite";
11
11
 
12
12
  // src/render/vite-plugin-root.ts
13
- import path2 from "path";
13
+ import path3 from "node:path";
14
+
15
+ // src/core/elements.ts
16
+ import fs2 from "node:fs";
17
+ import path2 from "node:path";
14
18
  import glob from "tiny-glob";
19
+ import { searchForWorkspaceRoot } from "vite";
15
20
 
16
21
  // src/core/fsutils.ts
17
22
  import { promises as fs } from "node:fs";
@@ -58,60 +63,84 @@ async function isDirectory(dirpath) {
58
63
  function fileExists(filepath) {
59
64
  return fs.access(filepath).then(() => true).catch(() => false);
60
65
  }
66
+ async function directoryContains(dirpath, subpath) {
67
+ const outer = await fs.realpath(dirpath);
68
+ const inner = await fs.realpath(subpath);
69
+ const rel = path.relative(outer, inner);
70
+ return !rel.startsWith("..");
71
+ }
61
72
 
62
- // src/render/vite-plugin-root.ts
63
- var JSX_ELEMENTS_REGEX = /jsxs?\("(\w[\w-]+\w)"/g;
64
- var HTML_ELEMENTS_REGEX = /<(\w[\w-]+\w)/g;
65
- function pluginRoot(options) {
73
+ // src/core/elements.ts
74
+ async function getElements(rootConfig) {
66
75
  var _a, _b;
67
- const elementsVirtualId = "virtual:root-elements";
68
- const resolvedElementsVirtualId = "\0" + elementsVirtualId;
69
- const rootDir = (options == null ? void 0 : options.rootDir) || process.cwd();
70
- const rootConfig = (options == null ? void 0 : options.rootConfig) || {};
76
+ const rootDir = rootConfig.rootDir;
77
+ const workspaceRoot = searchForWorkspaceRoot(rootDir);
71
78
  const elementsDirs = [path2.join(rootDir, "elements")];
72
- const includeDirs = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
73
- includeDirs.forEach((dirPath) => {
79
+ const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
80
+ const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
81
+ const excludeElement = (moduleId) => {
82
+ return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
83
+ };
84
+ for (const dirPath of elementsInclude) {
74
85
  const elementsDir = path2.resolve(rootDir, dirPath);
75
- if (!elementsDir.startsWith(rootDir)) {
86
+ if (!directoryContains(rootDir, elementsDir)) {
76
87
  throw new Error(
77
- `the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
88
+ `the elements dir (${dirPath}) should be within the project's workspace (${workspaceRoot})`
78
89
  );
79
90
  }
80
91
  elementsDirs.push(elementsDir);
81
- });
82
- const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
83
- const excludeElement = (moduleId) => {
84
- return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
85
- };
86
- let elementMap;
87
- async function updateElementMap() {
88
- elementMap = {};
89
- await Promise.all(
90
- elementsDirs.map(async (dirPath) => {
91
- const dirExists = await isDirectory(dirPath);
92
- if (!dirExists) {
93
- return;
94
- }
95
- const files = await glob("**/*", { cwd: dirPath });
96
- files.forEach((file) => {
97
- const parts = path2.parse(file);
98
- if (isJsFile(parts.base)) {
99
- const fullPath = path2.join(dirPath, file);
100
- const moduleId = fullPath.slice(rootDir.length);
101
- if (!excludeElement(moduleId)) {
102
- elementMap[parts.name] = moduleId;
103
- }
92
+ }
93
+ const elementMap = {};
94
+ for (const dirPath of elementsDirs) {
95
+ if (await isDirectory(dirPath)) {
96
+ const elementFiles = await glob("**/*", { cwd: dirPath });
97
+ elementFiles.forEach((file) => {
98
+ const parts = path2.parse(file);
99
+ if (isJsFile(parts.base)) {
100
+ const filePath = path2.join(dirPath, file);
101
+ const src = path2.relative(rootDir, filePath);
102
+ const realPath = fs2.realpathSync(filePath);
103
+ if (!excludeElement(src)) {
104
+ elementMap[parts.name] = {
105
+ src,
106
+ filePath,
107
+ realPath
108
+ };
104
109
  }
105
- });
106
- })
107
- );
110
+ }
111
+ });
112
+ }
108
113
  }
114
+ return elementMap;
115
+ }
116
+
117
+ // src/render/vite-plugin-root.ts
118
+ var JSX_ELEMENTS_REGEX = /jsxs?\("(\w[\w-]+\w)"/g;
119
+ var HTML_ELEMENTS_REGEX = /<(\w[\w-]+\w)/g;
120
+ async function pluginRoot(options) {
121
+ const elementsVirtualId = "virtual:root-elements";
122
+ const resolvedElementsVirtualId = "\0" + elementsVirtualId;
123
+ const rootConfig = options.rootConfig;
124
+ let tagNameToElement;
125
+ const customElementFiles = /* @__PURE__ */ new Set();
126
+ async function updateElementMap() {
127
+ tagNameToElement = await getElements(rootConfig);
128
+ customElementFiles.clear();
129
+ Object.values(tagNameToElement).forEach((elementModule) => {
130
+ customElementFiles.add(elementModule.filePath);
131
+ customElementFiles.add(elementModule.realPath);
132
+ });
133
+ }
134
+ await updateElementMap();
109
135
  async function getElementImport(tagname) {
110
- if (!elementMap) {
136
+ if (!tagNameToElement) {
111
137
  await updateElementMap();
112
138
  }
113
- if (tagname in elementMap) {
114
- return elementMap[tagname];
139
+ if (tagname in tagNameToElement) {
140
+ const elementModule = tagNameToElement[tagname];
141
+ if (elementModule.filePath === elementModule.realPath) {
142
+ return elementModule.src;
143
+ }
115
144
  }
116
145
  return null;
117
146
  }
@@ -119,9 +148,7 @@ function pluginRoot(options) {
119
148
  if (!isJsFile(id)) {
120
149
  return false;
121
150
  }
122
- return elementsDirs.some((elementsDir) => {
123
- return id.startsWith(elementsDir);
124
- });
151
+ return customElementFiles.has(id);
125
152
  }
126
153
  return {
127
154
  name: "vite-plugin-root",
@@ -134,13 +161,13 @@ function pluginRoot(options) {
134
161
  async load(id) {
135
162
  if (id === resolvedElementsVirtualId) {
136
163
  await updateElementMap();
137
- return `export const elementsMap = ${JSON.stringify(elementMap)}`;
164
+ return `export const elementsMap = ${JSON.stringify(tagNameToElement)}`;
138
165
  }
139
166
  return null;
140
167
  },
141
168
  async transform(src, id) {
142
169
  if (isCustomElement(id)) {
143
- const idParts = path2.parse(id);
170
+ const idParts = path3.parse(id);
144
171
  const deps = /* @__PURE__ */ new Set();
145
172
  const tagnames = [
146
173
  ...src.matchAll(JSX_ELEMENTS_REGEX),
@@ -166,7 +193,7 @@ function pluginRoot(options) {
166
193
  })
167
194
  );
168
195
  if (importUrls.length > 0) {
169
- const importLines = importUrls.map((url) => `import '${url}';`).join("\n");
196
+ const importLines = importUrls.map((url) => `import '/${url}';`).join("\n");
170
197
  const code = `${src}
171
198
 
172
199
  // autogenerated by root:
@@ -182,28 +209,54 @@ ${importLines}
182
209
  }
183
210
 
184
211
  // src/render/asset-map/dev-asset-map.ts
185
- import path3 from "node:path";
212
+ import path4 from "node:path";
213
+ import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
186
214
  var DevServerAssetMap = class {
187
- constructor(moduleGraph) {
215
+ constructor(rootConfig, moduleGraph) {
216
+ this.rootConfig = rootConfig;
188
217
  this.moduleGraph = moduleGraph;
189
218
  }
190
- async get(moduleId) {
191
- const viteModule = await this.moduleGraph.getModuleByUrl(moduleId);
192
- if (!viteModule || !viteModule.id) {
219
+ async get(src) {
220
+ const file = path4.resolve(this.rootConfig.rootDir, src);
221
+ const viteModules = this.moduleGraph.getModulesByFile(file);
222
+ if (viteModules && viteModules.size > 0) {
223
+ const [viteModule] = viteModules;
224
+ return new DevServerAsset(src, {
225
+ assetMap: this,
226
+ viteModule
227
+ });
228
+ }
229
+ if (file.startsWith(this.rootConfig.rootDir)) {
230
+ const assetUrl = file.slice(this.rootConfig.rootDir.length);
193
231
  return {
194
- moduleId,
195
- assetUrl: moduleId,
232
+ src,
233
+ assetUrl,
196
234
  getCssDeps: async () => [],
197
- getJsDeps: async () => [moduleId]
235
+ getJsDeps: async () => [assetUrl]
198
236
  };
199
237
  }
200
- return new DevServerAsset(this, viteModule);
238
+ const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
239
+ if (await directoryContains(workspaceRoot, file)) {
240
+ const assetUrl = `/@fs/${file}`;
241
+ return {
242
+ src,
243
+ assetUrl,
244
+ getCssDeps: async () => [],
245
+ getJsDeps: async () => [assetUrl]
246
+ };
247
+ }
248
+ console.log(`could not find asset in asset map: ${src}`);
249
+ return null;
250
+ }
251
+ filePathToSrc(file) {
252
+ return path4.relative(this.rootConfig.rootDir, file);
201
253
  }
202
254
  };
203
255
  var DevServerAsset = class {
204
- constructor(assetMap, viteModule) {
205
- this.assetMap = assetMap;
206
- this.viteModule = viteModule;
256
+ constructor(src, options) {
257
+ this.src = src;
258
+ this.assetMap = options.assetMap;
259
+ this.viteModule = options.viteModule;
207
260
  this.moduleId = this.viteModule.id;
208
261
  this.assetUrl = this.viteModule.url;
209
262
  }
@@ -233,13 +286,17 @@ var DevServerAsset = class {
233
286
  return;
234
287
  }
235
288
  visited.add(asset.moduleId);
236
- const parts = path3.parse(asset.assetUrl);
289
+ const parts = path4.parse(asset.assetUrl);
237
290
  if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
238
291
  urls.add(asset.assetUrl);
239
292
  }
240
293
  asset.getImportedModules().forEach((viteModule) => {
241
- if (viteModule.id) {
242
- const importedAsset = new DevServerAsset(this.assetMap, viteModule);
294
+ if (viteModule.file) {
295
+ const src = this.assetMap.filePathToSrc(viteModule.file);
296
+ const importedAsset = new DevServerAsset(src, {
297
+ assetMap: this.assetMap,
298
+ viteModule
299
+ });
243
300
  this.collectJs(importedAsset, urls, visited);
244
301
  }
245
302
  });
@@ -255,15 +312,19 @@ var DevServerAsset = class {
255
312
  return;
256
313
  }
257
314
  visited.add(asset.assetUrl);
258
- if (asset.moduleId.endsWith(".scss")) {
259
- const parts = path3.parse(asset.assetUrl);
315
+ if (asset.src.endsWith(".scss")) {
316
+ const parts = path4.parse(asset.src);
260
317
  if (!parts.name.startsWith("_")) {
261
318
  urls.add(asset.assetUrl);
262
319
  }
263
320
  }
264
321
  asset.getImportedModules().forEach((viteModule) => {
265
- if (viteModule.id) {
266
- const importedAsset = new DevServerAsset(this.assetMap, viteModule);
322
+ if (viteModule.file) {
323
+ const src = this.assetMap.filePathToSrc(viteModule.file);
324
+ const importedAsset = new DevServerAsset(src, {
325
+ assetMap: this.assetMap,
326
+ viteModule
327
+ });
267
328
  this.collectCss(importedAsset, urls, visited);
268
329
  }
269
330
  });
@@ -283,9 +344,9 @@ async function loadRootConfig(rootDir) {
283
344
  const configBundle = await bundleRequire({
284
345
  filepath: configPath
285
346
  });
286
- return configBundle.mod.default || {};
347
+ return Object.assign({}, configBundle.mod.default || {}, { rootDir });
287
348
  }
288
- return {};
349
+ return { rootDir };
289
350
  }
290
351
 
291
352
  // src/render/html-minify.ts
@@ -318,27 +379,66 @@ function rootProjectMiddleware(options) {
318
379
  };
319
380
  }
320
381
 
382
+ // src/cli/ports.ts
383
+ import { createServer } from "node:net";
384
+ function isPortOpen(port) {
385
+ return new Promise((resolve, reject) => {
386
+ const server = createServer();
387
+ server.on("error", (err) => {
388
+ if (err.code === "EADDRINUSE") {
389
+ resolve(false);
390
+ return;
391
+ }
392
+ reject(err);
393
+ });
394
+ server.on("close", () => {
395
+ resolve(true);
396
+ });
397
+ server.listen(port, () => {
398
+ server.close((err) => {
399
+ if (err) {
400
+ console.log(`error closing server: ${err}`);
401
+ reject(err);
402
+ }
403
+ });
404
+ });
405
+ });
406
+ }
407
+ async function findOpenPort(min, max) {
408
+ let port = min;
409
+ while (port <= max) {
410
+ const isOpen = await isPortOpen(port);
411
+ if (isOpen) {
412
+ return port;
413
+ }
414
+ port += 1;
415
+ }
416
+ throw new Error(`no ports open between ${min} and ${max}`);
417
+ }
418
+
321
419
  // src/cli/commands/dev.ts
322
- var __dirname = path4.dirname(fileURLToPath(import.meta.url));
420
+ var __dirname = path5.dirname(fileURLToPath(import.meta.url));
323
421
  async function dev(rootProjectDir) {
324
422
  process.env.NODE_ENV = "development";
325
- const rootDir = path4.resolve(rootProjectDir || process.cwd());
326
- const server = await createServer({ rootDir });
327
- const port = parseInt(process.env.PORT || "4007");
423
+ const rootDir = path5.resolve(rootProjectDir || process.cwd());
424
+ const defaultPort = parseInt(process.env.PORT || "4007");
425
+ const port = await findOpenPort(defaultPort, defaultPort + 10);
328
426
  console.log();
329
427
  console.log(`${dim("\u2503")} project: ${rootDir}`);
330
428
  console.log(`${dim("\u2503")} server: http://localhost:${port}`);
331
429
  console.log(`${dim("\u2503")} mode: development`);
332
430
  console.log();
431
+ const server = await createServer2({ rootDir, port });
333
432
  server.listen(port);
334
433
  }
335
- async function createServer(options) {
336
- const rootDir = path4.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
434
+ async function createServer2(options) {
435
+ const rootDir = path5.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
337
436
  const rootConfig = await loadRootConfig(rootDir);
437
+ const port = options == null ? void 0 : options.port;
338
438
  const server = express();
339
439
  server.disable("x-powered-by");
340
440
  server.use(rootProjectMiddleware({ rootDir, rootConfig }));
341
- server.use(await viteServerMiddleware({ rootDir, rootConfig }));
441
+ server.use(await viteServerMiddleware({ rootDir, rootConfig, port }));
342
442
  server.use(rootDevRendererMiddleware());
343
443
  const plugins = rootConfig.plugins || [];
344
444
  await configureServerPlugins(
@@ -358,56 +458,31 @@ async function createServer(options) {
358
458
  return server;
359
459
  }
360
460
  async function viteServerMiddleware(options) {
361
- var _a, _b, _c;
461
+ var _a, _b;
362
462
  const rootDir = options.rootDir;
363
463
  const rootConfig = options.rootConfig;
364
464
  const viteConfig = rootConfig.vite || {};
465
+ let hmrOptions = (_a = viteConfig.server) == null ? void 0 : _a.hmr;
466
+ if (typeof hmrOptions === "undefined" && options.port) {
467
+ hmrOptions = { port: options.port + 10 };
468
+ }
365
469
  const routeFiles = [];
366
- if (await isDirectory(path4.join(rootDir, "routes"))) {
470
+ if (await isDirectory(path5.join(rootDir, "routes"))) {
367
471
  const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
368
472
  pageFiles.forEach((file) => {
369
- const parts = path4.parse(file);
473
+ const parts = path5.parse(file);
370
474
  if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
371
475
  routeFiles.push(file);
372
476
  }
373
477
  });
374
478
  }
375
- const elementsDirs = [path4.join(rootDir, "elements")];
376
- const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
377
- const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
378
- const excludeElement = (moduleId) => {
379
- return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
380
- };
381
- for (const dirPath of elementsInclude) {
382
- const elementsDir = path4.resolve(rootDir, dirPath);
383
- if (!elementsDir.startsWith(rootDir)) {
384
- throw new Error(
385
- `the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
386
- );
387
- }
388
- elementsDirs.push(elementsDir);
389
- }
390
- const elements = [];
391
- for (const dirPath of elementsDirs) {
392
- if (await isDirectory(dirPath)) {
393
- const elementFiles = await glob2("**/*", { cwd: dirPath });
394
- elementFiles.forEach((file) => {
395
- const parts = path4.parse(file);
396
- if (isJsFile(parts.base)) {
397
- const fullPath = path4.join(dirPath, file);
398
- const moduleId = fullPath.slice(rootDir.length);
399
- if (!excludeElement(moduleId)) {
400
- elements.push(moduleId.slice(1));
401
- }
402
- }
403
- });
404
- }
405
- }
479
+ const elementsMap = await getElements(rootConfig);
480
+ const elements = Object.values(elementsMap).map((mod) => mod.src);
406
481
  const bundleScripts = [];
407
- if (await isDirectory(path4.join(rootDir, "bundles"))) {
408
- const bundleFiles = await glob2(path4.join(rootDir, "bundles/*"));
482
+ if (await isDirectory(path5.join(rootDir, "bundles"))) {
483
+ const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
409
484
  bundleFiles.forEach((file) => {
410
- const parts = path4.parse(file);
485
+ const parts = path5.parse(file);
411
486
  if (isJsFile(parts.base)) {
412
487
  bundleScripts.push(file);
413
488
  }
@@ -417,10 +492,11 @@ async function viteServerMiddleware(options) {
417
492
  ...viteConfig,
418
493
  mode: "development",
419
494
  root: rootDir,
420
- publicDir: path4.join(rootDir, "public"),
495
+ publicDir: path5.join(rootDir, "public"),
421
496
  server: {
422
497
  ...viteConfig.server || {},
423
- middlewareMode: true
498
+ middlewareMode: true,
499
+ hmr: hmrOptions
424
500
  },
425
501
  appType: "custom",
426
502
  optimizeDeps: {
@@ -429,7 +505,7 @@ async function viteServerMiddleware(options) {
429
505
  ...routeFiles,
430
506
  ...elements,
431
507
  ...bundleScripts,
432
- ...((_c = viteConfig.optimizeDeps) == null ? void 0 : _c.include) || []
508
+ ...((_b = viteConfig.optimizeDeps) == null ? void 0 : _b.include) || []
433
509
  ]
434
510
  },
435
511
  ssr: {
@@ -442,23 +518,23 @@ async function viteServerMiddleware(options) {
442
518
  jsxImportSource: "preact"
443
519
  },
444
520
  plugins: [
445
- pluginRoot({ rootDir, rootConfig }),
521
+ pluginRoot({ rootConfig }),
446
522
  ...viteConfig.plugins || [],
447
523
  ...getVitePlugins(rootConfig.plugins || [])
448
524
  ]
449
525
  });
450
- return async (req, res, next) => {
526
+ return (req, res, next) => {
451
527
  req.viteServer = viteServer;
452
528
  viteServer.middlewares(req, res, next);
453
529
  };
454
530
  }
455
531
  function rootDevRendererMiddleware() {
456
- const renderModulePath = path4.resolve(__dirname, "./render.js");
532
+ const renderModulePath = path5.resolve(__dirname, "./render.js");
457
533
  return async (req, _, next) => {
458
534
  const rootConfig = req.rootConfig;
459
535
  const viteServer = req.viteServer;
460
536
  const render = await viteServer.ssrLoadModule(renderModulePath);
461
- const assetMap = new DevServerAssetMap(viteServer.moduleGraph);
537
+ const assetMap = new DevServerAssetMap(rootConfig, viteServer.moduleGraph);
462
538
  req.renderer = new render.Renderer(rootConfig, { assetMap });
463
539
  next();
464
540
  };
@@ -501,7 +577,7 @@ function rootDevServerMiddleware() {
501
577
  function rootDevServer404Middleware() {
502
578
  return async (req, res) => {
503
579
  const url = req.originalUrl;
504
- const ext = path4.extname(url);
580
+ const ext = path5.extname(url);
505
581
  const renderer = req.renderer;
506
582
  if (!ext) {
507
583
  const data = await renderer.renderDevServer404();
@@ -514,7 +590,7 @@ function rootDevServer404Middleware() {
514
590
  }
515
591
 
516
592
  // src/cli/commands/build.ts
517
- import path5 from "node:path";
593
+ import path6 from "node:path";
518
594
  import { fileURLToPath as fileURLToPath2 } from "node:url";
519
595
  import fsExtra2 from "fs-extra";
520
596
  import glob3 from "tiny-glob";
@@ -523,37 +599,40 @@ import { build as viteBuild } from "vite";
523
599
  // src/render/asset-map/build-asset-map.ts
524
600
  var BuildAssetMap = class {
525
601
  constructor() {
526
- this.moduleIdToAsset = /* @__PURE__ */ new Map();
602
+ this.srcToAsset = /* @__PURE__ */ new Map();
527
603
  }
528
- async get(moduleId) {
529
- return this.moduleIdToAsset.get(moduleId) || null;
604
+ async get(src) {
605
+ const asset = this.srcToAsset.get(src);
606
+ if (asset) {
607
+ return asset;
608
+ }
609
+ console.log(`could not find build asset: ${src}`);
610
+ return null;
530
611
  }
531
612
  add(asset) {
532
- this.moduleIdToAsset.set(asset.moduleId, asset);
613
+ this.srcToAsset.set(asset.src, asset);
533
614
  }
534
615
  toJson() {
535
616
  const result = {};
536
- for (const moduleId of this.moduleIdToAsset.keys()) {
537
- result[moduleId] = this.moduleIdToAsset.get(moduleId).toJson();
617
+ for (const src of this.srcToAsset.keys()) {
618
+ result[src] = this.srcToAsset.get(src).toJson();
538
619
  }
539
620
  return result;
540
621
  }
541
622
  static fromViteManifest(viteManifest, elementMap) {
542
623
  const assetMap = new BuildAssetMap();
543
- const elementModuleIds = /* @__PURE__ */ new Set();
624
+ const elementFiles = /* @__PURE__ */ new Set();
544
625
  Object.values(elementMap).forEach(
545
- (moduleId) => elementModuleIds.add(moduleId)
626
+ (elementModule) => elementFiles.add(elementModule.src)
546
627
  );
547
628
  Object.keys(viteManifest).forEach((manifestKey) => {
548
- const moduleId = `/${manifestKey}`;
629
+ const src = manifestKey;
549
630
  const manifestChunk = viteManifest[manifestKey];
550
- const isElement = elementModuleIds.has(moduleId);
631
+ const isElement = elementFiles.has(src);
551
632
  const assetData = {
552
- moduleId,
633
+ src,
553
634
  assetUrl: `/${manifestChunk.file}`,
554
- importedModules: (manifestChunk.imports || []).map(
555
- (relPath) => `/${relPath}`
556
- ),
635
+ importedModules: manifestChunk.imports || [],
557
636
  importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
558
637
  isElement
559
638
  };
@@ -573,7 +652,7 @@ var BuildAssetMap = class {
573
652
  var BuildAsset = class {
574
653
  constructor(assetMap, assetData) {
575
654
  this.assetMap = assetMap;
576
- this.moduleId = assetData.moduleId;
655
+ this.src = assetData.src;
577
656
  this.assetUrl = assetData.assetUrl;
578
657
  this.importedModules = assetData.importedModules;
579
658
  this.importedCss = assetData.importedCss;
@@ -595,19 +674,19 @@ var BuildAsset = class {
595
674
  if (!asset) {
596
675
  return;
597
676
  }
598
- if (!asset.moduleId) {
677
+ if (!asset.src) {
599
678
  return;
600
679
  }
601
- if (visited.has(asset.moduleId)) {
680
+ if (visited.has(asset.src)) {
602
681
  return;
603
682
  }
604
- visited.add(asset.moduleId);
683
+ visited.add(asset.src);
605
684
  if (asset.isElement) {
606
685
  urls.add(asset.assetUrl);
607
686
  }
608
687
  await Promise.all(
609
- asset.importedModules.map(async (moduleId) => {
610
- const importedAsset = await this.assetMap.get(moduleId);
688
+ asset.importedModules.map(async (src) => {
689
+ const importedAsset = await this.assetMap.get(src);
611
690
  this.collectJs(importedAsset, urls, visited);
612
691
  })
613
692
  );
@@ -619,10 +698,10 @@ var BuildAsset = class {
619
698
  if (!asset.assetUrl) {
620
699
  return;
621
700
  }
622
- if (visited.has(asset.moduleId)) {
701
+ if (visited.has(asset.src)) {
623
702
  return;
624
703
  }
625
- visited.add(asset.moduleId);
704
+ visited.add(asset.src);
626
705
  if (asset.importedCss) {
627
706
  asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
628
707
  }
@@ -635,7 +714,7 @@ var BuildAsset = class {
635
714
  }
636
715
  toJson() {
637
716
  return {
638
- moduleId: this.moduleId,
717
+ src: this.src,
639
718
  assetUrl: this.assetUrl,
640
719
  importedModules: this.importedModules,
641
720
  importedCss: this.importedCss,
@@ -646,12 +725,11 @@ var BuildAsset = class {
646
725
 
647
726
  // src/cli/commands/build.ts
648
727
  import { dim as dim2 } from "kleur/colors";
649
- var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
728
+ var __dirname2 = path6.dirname(fileURLToPath2(import.meta.url));
650
729
  async function build(rootProjectDir, options) {
651
- var _a, _b;
652
- const rootDir = path5.resolve(rootProjectDir || process.cwd());
730
+ const rootDir = path6.resolve(rootProjectDir || process.cwd());
653
731
  const rootConfig = await loadRootConfig(rootDir);
654
- const distDir = path5.join(rootDir, "dist");
732
+ const distDir = path6.join(rootDir, "dist");
655
733
  const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
656
734
  const mode = (options == null ? void 0 : options.mode) || "production";
657
735
  console.log();
@@ -661,62 +739,33 @@ async function build(rootProjectDir, options) {
661
739
  console.log();
662
740
  await rmDir(distDir);
663
741
  await makeDir(distDir);
664
- const pages = [];
665
- if (await isDirectory(path5.join(rootDir, "routes"))) {
666
- const pageFiles = await glob3(path5.join(rootDir, "routes/**/*"));
742
+ const routeFiles = [];
743
+ if (await isDirectory(path6.join(rootDir, "routes"))) {
744
+ const pageFiles = await glob3("routes/**/*", { cwd: rootDir });
667
745
  pageFiles.forEach((file) => {
668
- const parts = path5.parse(file);
746
+ const parts = path6.parse(file);
669
747
  if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
670
- pages.push(file);
748
+ routeFiles.push(path6.resolve(rootDir, file));
671
749
  }
672
750
  });
673
751
  }
674
- const elementsDirs = [path5.join(rootDir, "elements")];
675
- const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
676
- const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
677
- const excludeElement = (moduleId) => {
678
- return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
679
- };
680
- for (const dirPath of elementsInclude) {
681
- const elementsDir = path5.resolve(rootDir, dirPath);
682
- if (!elementsDir.startsWith(rootDir)) {
683
- throw new Error(
684
- `the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
685
- );
686
- }
687
- elementsDirs.push(elementsDir);
688
- }
689
- const elements = [];
690
- const elementMap = {};
691
- for (const dirPath of elementsDirs) {
692
- if (await isDirectory(dirPath)) {
693
- const elementFiles = await glob3("**/*", { cwd: dirPath });
694
- elementFiles.forEach((file) => {
695
- const parts = path5.parse(file);
696
- if (isJsFile(parts.base)) {
697
- const fullPath = path5.join(dirPath, file);
698
- const moduleId = fullPath.slice(rootDir.length);
699
- if (!excludeElement(moduleId)) {
700
- elements.push(fullPath);
701
- elementMap[parts.name] = moduleId;
702
- }
703
- }
704
- });
705
- }
706
- }
752
+ const elementsMap = await getElements(rootConfig);
753
+ const elements = Object.values(elementsMap).map(
754
+ (mod) => path6.resolve(rootDir, mod.src)
755
+ );
707
756
  const bundleScripts = [];
708
- if (await isDirectory(path5.join(rootDir, "bundles"))) {
709
- const bundleFiles = await glob3(path5.join(rootDir, "bundles/*"));
757
+ if (await isDirectory(path6.join(rootDir, "bundles"))) {
758
+ const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
710
759
  bundleFiles.forEach((file) => {
711
- const parts = path5.parse(file);
760
+ const parts = path6.parse(file);
712
761
  if (isJsFile(parts.base)) {
713
- bundleScripts.push(file);
762
+ bundleScripts.push(path6.resolve(rootDir, file));
714
763
  }
715
764
  });
716
765
  }
717
766
  const viteConfig = rootConfig.vite || {};
718
767
  const vitePlugins = [
719
- pluginRoot({ rootDir, rootConfig }),
768
+ pluginRoot({ rootConfig }),
720
769
  ...viteConfig.plugins || [],
721
770
  ...getVitePlugins(rootConfig.plugins || [])
722
771
  ];
@@ -736,14 +785,14 @@ async function build(rootProjectDir, options) {
736
785
  publicDir: false,
737
786
  build: {
738
787
  rollupOptions: {
739
- input: [path5.resolve(__dirname2, "./render.js")],
788
+ input: [path6.resolve(__dirname2, "./render.js")],
740
789
  output: {
741
790
  format: "esm",
742
791
  chunkFileNames: "chunks/[name].[hash].js",
743
792
  assetFileNames: "assets/[name].[hash][extname]"
744
793
  }
745
794
  },
746
- outDir: path5.join(distDir, "server"),
795
+ outDir: path6.join(distDir, "server"),
747
796
  ssr: true,
748
797
  ssrManifest: false,
749
798
  cssCodeSplit: true,
@@ -761,14 +810,14 @@ async function build(rootProjectDir, options) {
761
810
  publicDir: false,
762
811
  build: {
763
812
  rollupOptions: {
764
- input: [...pages, ...elements, ...bundleScripts],
813
+ input: [...routeFiles, ...elements, ...bundleScripts],
765
814
  output: {
766
815
  format: "esm",
767
816
  chunkFileNames: "chunks/[name].[hash].js",
768
817
  assetFileNames: "assets/[name].[hash][extname]"
769
818
  }
770
819
  },
771
- outDir: path5.join(distDir, "client"),
820
+ outDir: path6.join(distDir, "client"),
772
821
  ssr: false,
773
822
  ssrManifest: false,
774
823
  manifest: true,
@@ -780,24 +829,24 @@ async function build(rootProjectDir, options) {
780
829
  }
781
830
  });
782
831
  const viteManifest = await loadJson(
783
- path5.join(distDir, "client/manifest.json")
832
+ path6.join(distDir, "client/manifest.json")
784
833
  );
785
- const assetMap = BuildAssetMap.fromViteManifest(viteManifest, elementMap);
834
+ const assetMap = BuildAssetMap.fromViteManifest(viteManifest, elementsMap);
786
835
  writeFile(
787
- path5.join(distDir, "client/root-manifest.json"),
836
+ path6.join(distDir, "client/root-manifest.json"),
788
837
  JSON.stringify(assetMap.toJson(), null, 2)
789
838
  );
790
- const buildDir = path5.join(distDir, "html");
791
- const publicDir = path5.join(rootDir, "public");
792
- if (fsExtra2.existsSync(path5.join(rootDir, "public"))) {
839
+ const buildDir = path6.join(distDir, "html");
840
+ const publicDir = path6.join(rootDir, "public");
841
+ if (fsExtra2.existsSync(path6.join(rootDir, "public"))) {
793
842
  fsExtra2.copySync(publicDir, buildDir);
794
843
  } else {
795
844
  makeDir(buildDir);
796
845
  }
797
- copyDir(path5.join(distDir, "client/assets"), path5.join(buildDir, "assets"));
798
- copyDir(path5.join(distDir, "client/chunks"), path5.join(buildDir, "chunks"));
846
+ copyDir(path6.join(distDir, "client/assets"), path6.join(buildDir, "assets"));
847
+ copyDir(path6.join(distDir, "client/chunks"), path6.join(buildDir, "chunks"));
799
848
  if (!ssrOnly) {
800
- const render = await import(path5.join(distDir, "server/render.js"));
849
+ const render = await import(path6.join(distDir, "server/render.js"));
801
850
  const renderer = new render.Renderer(rootConfig, { assetMap });
802
851
  const sitemap = await renderer.getSitemap();
803
852
  await Promise.all(
@@ -806,13 +855,13 @@ async function build(rootProjectDir, options) {
806
855
  const data = await renderer.renderRoute(route, {
807
856
  routeParams: params
808
857
  });
809
- let outPath = path5.join(distDir, `html${urlPath}`, "index.html");
858
+ let outPath = path6.join(distDir, `html${urlPath}`, "index.html");
810
859
  if (outPath.endsWith("404/index.html")) {
811
860
  outPath = outPath.replace("404/index.html", "404.html");
812
861
  }
813
862
  const html = await htmlMinify(data.html || "");
814
863
  await writeFile(outPath, html);
815
- const relPath = outPath.slice(path5.dirname(distDir).length + 1);
864
+ const relPath = outPath.slice(path6.dirname(distDir).length + 1);
816
865
  console.log(`saved ${relPath}`);
817
866
  })
818
867
  );
@@ -820,15 +869,15 @@ async function build(rootProjectDir, options) {
820
869
  }
821
870
 
822
871
  // src/cli/commands/preview.ts
823
- import path6 from "node:path";
872
+ import path7 from "node:path";
824
873
  import { default as express2 } from "express";
825
874
  import { dim as dim3 } from "kleur/colors";
826
875
  import sirv from "sirv";
827
876
  import compression from "compression";
828
877
  async function preview(rootProjectDir) {
829
878
  process.env.NODE_ENV = "development";
830
- const rootDir = path6.resolve(rootProjectDir || process.cwd());
831
- const server = await createServer2({ rootDir });
879
+ const rootDir = path7.resolve(rootProjectDir || process.cwd());
880
+ const server = await createServer3({ rootDir });
832
881
  const port = parseInt(process.env.PORT || "4007");
833
882
  console.log();
834
883
  console.log(`${dim3("\u2503")} project: ${rootDir}`);
@@ -837,10 +886,10 @@ async function preview(rootProjectDir) {
837
886
  console.log();
838
887
  server.listen(port);
839
888
  }
840
- async function createServer2(options) {
889
+ async function createServer3(options) {
841
890
  const rootDir = options.rootDir;
842
891
  const rootConfig = await loadRootConfig(rootDir);
843
- const distDir = path6.join(rootDir, "dist");
892
+ const distDir = path7.join(rootDir, "dist");
844
893
  const server = express2();
845
894
  server.disable("x-powered-by");
846
895
  server.use(compression());
@@ -855,7 +904,7 @@ async function createServer2(options) {
855
904
  userMiddlewares.forEach((middleware) => {
856
905
  server.use(middleware);
857
906
  });
858
- const publicDir = path6.join(distDir, "html");
907
+ const publicDir = path7.join(distDir, "html");
859
908
  server.use(sirv(publicDir, { dev: false }));
860
909
  server.use(rootPreviewServerMiddleware());
861
910
  },
@@ -866,8 +915,8 @@ async function createServer2(options) {
866
915
  }
867
916
  async function rootPreviewRendererMiddleware(options) {
868
917
  const { distDir, rootConfig } = options;
869
- const render = await import(path6.join(distDir, "server/render.js"));
870
- const manifestPath = path6.join(distDir, "client/root-manifest.json");
918
+ const render = await import(path7.join(distDir, "server/render.js"));
919
+ const manifestPath = path7.join(distDir, "client/root-manifest.json");
871
920
  if (!await fileExists(manifestPath)) {
872
921
  throw new Error(
873
922
  `could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
@@ -911,15 +960,15 @@ function rootPreviewServerMiddleware() {
911
960
  }
912
961
 
913
962
  // src/cli/commands/start.ts
914
- import path7 from "node:path";
963
+ import path8 from "node:path";
915
964
  import { default as express3 } from "express";
916
965
  import { dim as dim4 } from "kleur/colors";
917
966
  import sirv2 from "sirv";
918
967
  import compression2 from "compression";
919
968
  async function start(rootProjectDir) {
920
969
  process.env.NODE_ENV = "production";
921
- const rootDir = path7.resolve(rootProjectDir || process.cwd());
922
- const server = await createServer3({ rootDir });
970
+ const rootDir = path8.resolve(rootProjectDir || process.cwd());
971
+ const server = await createServer4({ rootDir });
923
972
  const port = parseInt(process.env.PORT || "4007");
924
973
  console.log();
925
974
  console.log(`${dim4("\u2503")} project: ${rootDir}`);
@@ -928,10 +977,10 @@ async function start(rootProjectDir) {
928
977
  console.log();
929
978
  server.listen(port);
930
979
  }
931
- async function createServer3(options) {
980
+ async function createServer4(options) {
932
981
  const rootDir = options.rootDir;
933
982
  const rootConfig = await loadRootConfig(rootDir);
934
- const distDir = path7.join(rootDir, "dist");
983
+ const distDir = path8.join(rootDir, "dist");
935
984
  const server = express3();
936
985
  server.disable("x-powered-by");
937
986
  server.use(compression2());
@@ -946,7 +995,7 @@ async function createServer3(options) {
946
995
  userMiddlewares.forEach((middleware) => {
947
996
  server.use(middleware);
948
997
  });
949
- const publicDir = path7.join(distDir, "html");
998
+ const publicDir = path8.join(distDir, "html");
950
999
  server.use(sirv2(publicDir, { dev: false }));
951
1000
  server.use(rootProdServerMiddleware());
952
1001
  },
@@ -957,8 +1006,8 @@ async function createServer3(options) {
957
1006
  }
958
1007
  async function rootProdRendererMiddleware(options) {
959
1008
  const { distDir, rootConfig } = options;
960
- const render = await import(path7.join(distDir, "server/render.js"));
961
- const manifestPath = path7.join(distDir, "client/root-manifest.json");
1009
+ const render = await import(path8.join(distDir, "server/render.js"));
1010
+ const manifestPath = path8.join(distDir, "client/root-manifest.json");
962
1011
  if (!await fileExists(manifestPath)) {
963
1012
  throw new Error(
964
1013
  `could not find ${manifestPath}. run \`root build\` before \`root preview\`.`