@constela/start 1.2.2 → 1.2.4
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.
|
@@ -1492,7 +1492,7 @@ function normalizeDataSourcePatterns(projectRoot, pageDir, dataSources) {
|
|
|
1492
1492
|
}
|
|
1493
1493
|
return result;
|
|
1494
1494
|
}
|
|
1495
|
-
async function loadJsonPage(baseDir, pagePath) {
|
|
1495
|
+
async function loadJsonPage(baseDir, pagePath, options) {
|
|
1496
1496
|
const filePath = join6(baseDir, pagePath);
|
|
1497
1497
|
const resolvedBase = resolve3(baseDir);
|
|
1498
1498
|
const resolvedPath = resolve3(filePath);
|
|
@@ -1523,7 +1523,8 @@ async function loadJsonPage(baseDir, pagePath) {
|
|
|
1523
1523
|
validateVersion(page.version);
|
|
1524
1524
|
const pageDir = dirname2(filePath);
|
|
1525
1525
|
const resolvedImports = await resolveImports(pageDir, page.imports, baseDir);
|
|
1526
|
-
const
|
|
1526
|
+
const patternBaseDir = options?.routesDir ?? pageDir;
|
|
1527
|
+
const normalizedData = normalizeDataSourcePatterns(baseDir, patternBaseDir, page.data);
|
|
1527
1528
|
const loadedData = await loadPageData(baseDir, normalizedData, { imports: resolvedImports });
|
|
1528
1529
|
const widgets = await loadWidgets(pageDir, page.widgets, baseDir);
|
|
1529
1530
|
return {
|
|
@@ -1831,9 +1832,11 @@ async function convertToCompiledProgram(pageInfo) {
|
|
|
1831
1832
|
}
|
|
1832
1833
|
var JsonPageLoader = class {
|
|
1833
1834
|
projectRoot;
|
|
1835
|
+
routesDir;
|
|
1834
1836
|
cache = /* @__PURE__ */ new Map();
|
|
1835
|
-
constructor(projectRoot) {
|
|
1837
|
+
constructor(projectRoot, options) {
|
|
1836
1838
|
this.projectRoot = projectRoot;
|
|
1839
|
+
this.routesDir = options?.routesDir;
|
|
1837
1840
|
}
|
|
1838
1841
|
/**
|
|
1839
1842
|
* Load a JSON page with full resolution
|
|
@@ -1842,7 +1845,9 @@ var JsonPageLoader = class {
|
|
|
1842
1845
|
if (this.cache.has(pagePath)) {
|
|
1843
1846
|
return this.cache.get(pagePath);
|
|
1844
1847
|
}
|
|
1845
|
-
const pageInfo = await loadJsonPage(this.projectRoot, pagePath
|
|
1848
|
+
const pageInfo = await loadJsonPage(this.projectRoot, pagePath, {
|
|
1849
|
+
routesDir: this.routesDir
|
|
1850
|
+
});
|
|
1846
1851
|
this.cache.set(pagePath, pageInfo);
|
|
1847
1852
|
return pageInfo;
|
|
1848
1853
|
}
|
|
@@ -2168,14 +2173,15 @@ h1 { color: #666; }
|
|
|
2168
2173
|
}
|
|
2169
2174
|
|
|
2170
2175
|
// src/build/index.ts
|
|
2171
|
-
import { existsSync as
|
|
2176
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
2172
2177
|
import { mkdir as mkdir2, writeFile, cp, readdir } from "fs/promises";
|
|
2173
|
-
import { join as join9, dirname as dirname5, relative as relative2, basename as basename4, isAbsolute as
|
|
2178
|
+
import { join as join9, dirname as dirname5, relative as relative2, basename as basename4, isAbsolute as isAbsolute3, resolve as resolve4 } from "path";
|
|
2174
2179
|
|
|
2175
2180
|
// src/build/bundler.ts
|
|
2176
2181
|
import * as esbuild from "esbuild";
|
|
2182
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2177
2183
|
import { mkdir } from "fs/promises";
|
|
2178
|
-
import { join as join8, dirname as dirname4 } from "path";
|
|
2184
|
+
import { join as join8, dirname as dirname4, isAbsolute as isAbsolute2 } from "path";
|
|
2179
2185
|
import { fileURLToPath } from "url";
|
|
2180
2186
|
var __dirname = dirname4(fileURLToPath(import.meta.url));
|
|
2181
2187
|
async function bundleRuntime(options) {
|
|
@@ -2205,8 +2211,47 @@ async function bundleRuntime(options) {
|
|
|
2205
2211
|
}
|
|
2206
2212
|
return "/_constela/runtime.js";
|
|
2207
2213
|
}
|
|
2214
|
+
async function bundleCSS(options) {
|
|
2215
|
+
const cssFiles = Array.isArray(options.css) ? options.css : [options.css];
|
|
2216
|
+
const outFile = join8(options.outDir, "_constela", "styles.css");
|
|
2217
|
+
await mkdir(dirname4(outFile), { recursive: true });
|
|
2218
|
+
const resolvedCssFiles = cssFiles.map((f) => isAbsolute2(f) ? f : join8(process.cwd(), f));
|
|
2219
|
+
for (const fullPath of resolvedCssFiles) {
|
|
2220
|
+
if (!existsSync7(fullPath)) {
|
|
2221
|
+
throw new Error(`CSS file not found: ${fullPath}`);
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
try {
|
|
2225
|
+
if (resolvedCssFiles.length === 1) {
|
|
2226
|
+
await esbuild.build({
|
|
2227
|
+
entryPoints: resolvedCssFiles,
|
|
2228
|
+
bundle: true,
|
|
2229
|
+
outfile: outFile,
|
|
2230
|
+
minify: options.minify ?? true,
|
|
2231
|
+
loader: { ".css": "css" }
|
|
2232
|
+
});
|
|
2233
|
+
} else {
|
|
2234
|
+
const virtualEntry = resolvedCssFiles.map((f) => `@import "${f}";`).join("\n");
|
|
2235
|
+
await esbuild.build({
|
|
2236
|
+
stdin: {
|
|
2237
|
+
contents: virtualEntry,
|
|
2238
|
+
loader: "css",
|
|
2239
|
+
resolveDir: process.cwd()
|
|
2240
|
+
},
|
|
2241
|
+
bundle: true,
|
|
2242
|
+
outfile: outFile,
|
|
2243
|
+
minify: options.minify ?? true
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
} catch (error) {
|
|
2247
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2248
|
+
throw new Error(`Failed to bundle CSS to ${outFile}: ${message}`);
|
|
2249
|
+
}
|
|
2250
|
+
return "/_constela/styles.css";
|
|
2251
|
+
}
|
|
2208
2252
|
|
|
2209
2253
|
// src/build/index.ts
|
|
2254
|
+
var DEFAULT_PUBLIC_DIR2 = "public";
|
|
2210
2255
|
function isDynamicRoute(pattern) {
|
|
2211
2256
|
return pattern.includes(":") || pattern.includes("*");
|
|
2212
2257
|
}
|
|
@@ -2233,7 +2278,7 @@ async function loadGetStaticPaths(pageFile) {
|
|
|
2233
2278
|
const dir = dirname5(pageFile);
|
|
2234
2279
|
const baseName = basename4(pageFile, ".json");
|
|
2235
2280
|
const pathsFile = join9(dir, `${baseName}.paths.ts`);
|
|
2236
|
-
if (!
|
|
2281
|
+
if (!existsSync8(pathsFile)) {
|
|
2237
2282
|
return null;
|
|
2238
2283
|
}
|
|
2239
2284
|
try {
|
|
@@ -2274,7 +2319,7 @@ async function loadGetStaticPaths(pageFile) {
|
|
|
2274
2319
|
}
|
|
2275
2320
|
async function loadLayout2(layoutName, layoutsDir) {
|
|
2276
2321
|
const layoutPath = join9(layoutsDir, `${layoutName}.json`);
|
|
2277
|
-
if (!
|
|
2322
|
+
if (!existsSync8(layoutPath)) {
|
|
2278
2323
|
throw new Error(`Layout "${layoutName}" not found at ${layoutPath}`);
|
|
2279
2324
|
}
|
|
2280
2325
|
try {
|
|
@@ -2382,7 +2427,7 @@ async function processLayouts(pageInfo, layoutsDir) {
|
|
|
2382
2427
|
}
|
|
2383
2428
|
return updatedPageInfo;
|
|
2384
2429
|
}
|
|
2385
|
-
async function renderPageToHtml(program, params, runtimePath) {
|
|
2430
|
+
async function renderPageToHtml(program, params, runtimePath, cssPath) {
|
|
2386
2431
|
const normalizedProgram = {
|
|
2387
2432
|
...program,
|
|
2388
2433
|
view: normalizeViewNode(structuredClone(program.view))
|
|
@@ -2398,11 +2443,12 @@ async function renderPageToHtml(program, params, runtimePath) {
|
|
|
2398
2443
|
query: {},
|
|
2399
2444
|
path: "/"
|
|
2400
2445
|
};
|
|
2446
|
+
const cssLinkTag = cssPath ? `<link rel="stylesheet" href="${cssPath}">` : void 0;
|
|
2401
2447
|
const hydrationScript = generateHydrationScript(normalizedProgram, void 0, routeContext);
|
|
2402
|
-
return wrapHtml(content, hydrationScript,
|
|
2448
|
+
return wrapHtml(content, hydrationScript, cssLinkTag, runtimePath ? { runtimePath } : void 0);
|
|
2403
2449
|
}
|
|
2404
2450
|
async function copyPublicDir(publicDir, outDir, generatedFiles) {
|
|
2405
|
-
if (!
|
|
2451
|
+
if (!existsSync8(publicDir)) {
|
|
2406
2452
|
return;
|
|
2407
2453
|
}
|
|
2408
2454
|
await copyDirRecursive(publicDir, outDir, generatedFiles);
|
|
@@ -2440,7 +2486,7 @@ function validateJsonPage(content, filePath) {
|
|
|
2440
2486
|
async function build2(options) {
|
|
2441
2487
|
const outDir = options?.outDir ?? "dist";
|
|
2442
2488
|
const routesDir = options?.routesDir ?? "src/routes";
|
|
2443
|
-
const publicDir = options?.publicDir;
|
|
2489
|
+
const publicDir = options?.publicDir ?? DEFAULT_PUBLIC_DIR2;
|
|
2444
2490
|
const layoutsDir = options?.layoutsDir;
|
|
2445
2491
|
const generatedFiles = [];
|
|
2446
2492
|
await mkdir2(outDir, { recursive: true });
|
|
@@ -2470,7 +2516,14 @@ async function build2(options) {
|
|
|
2470
2516
|
};
|
|
2471
2517
|
}
|
|
2472
2518
|
const runtimePath = await bundleRuntime({ outDir });
|
|
2473
|
-
|
|
2519
|
+
let cssPath;
|
|
2520
|
+
if (options?.css) {
|
|
2521
|
+
cssPath = await bundleCSS({
|
|
2522
|
+
outDir,
|
|
2523
|
+
css: options.css
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
const absoluteRoutesDir = isAbsolute3(routesDir) ? routesDir : resolve4(routesDir);
|
|
2474
2527
|
const projectRoot = dirname5(dirname5(absoluteRoutesDir));
|
|
2475
2528
|
for (const route of jsonPages) {
|
|
2476
2529
|
const relPathFromRoutesDir = relative2(absoluteRoutesDir, route.file);
|
|
@@ -2478,23 +2531,31 @@ async function build2(options) {
|
|
|
2478
2531
|
const content = readFileSync5(route.file, "utf-8");
|
|
2479
2532
|
const page = validateJsonPage(content, route.file);
|
|
2480
2533
|
if (isDynamicRoute(route.pattern)) {
|
|
2481
|
-
const
|
|
2482
|
-
|
|
2534
|
+
const loader = new JsonPageLoader(projectRoot, { routesDir: absoluteRoutesDir });
|
|
2535
|
+
let pageInfo = await loader.loadPage(relPathFromProjectRoot);
|
|
2536
|
+
let staticPathsResult = null;
|
|
2537
|
+
if (pageInfo.page.getStaticPaths) {
|
|
2538
|
+
staticPathsResult = await generateStaticPathsFromPage(
|
|
2539
|
+
pageInfo.page,
|
|
2540
|
+
pageInfo.loadedData
|
|
2541
|
+
);
|
|
2542
|
+
} else {
|
|
2543
|
+
const externalPaths = await loadGetStaticPaths(route.file);
|
|
2544
|
+
if (externalPaths) {
|
|
2545
|
+
staticPathsResult = externalPaths.paths.map((p) => ({ params: p.params }));
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
if (!staticPathsResult || staticPathsResult.length === 0) {
|
|
2483
2549
|
continue;
|
|
2484
2550
|
}
|
|
2485
|
-
if (
|
|
2486
|
-
|
|
2551
|
+
if (layoutsDir) {
|
|
2552
|
+
pageInfo = await processLayouts(pageInfo, layoutsDir);
|
|
2487
2553
|
}
|
|
2488
|
-
for (const pathEntry of
|
|
2554
|
+
for (const pathEntry of staticPathsResult) {
|
|
2489
2555
|
const params = pathEntry.params;
|
|
2490
2556
|
const outputPath = paramsToOutputPath(route.pattern, params, outDir);
|
|
2491
|
-
const loader = new JsonPageLoader(projectRoot);
|
|
2492
|
-
let pageInfo = await loader.loadPage(relPathFromProjectRoot);
|
|
2493
|
-
if (layoutsDir) {
|
|
2494
|
-
pageInfo = await processLayouts(pageInfo, layoutsDir);
|
|
2495
|
-
}
|
|
2496
2557
|
const program = await convertToCompiledProgram(pageInfo);
|
|
2497
|
-
const html = await renderPageToHtml(program, params, runtimePath);
|
|
2558
|
+
const html = await renderPageToHtml(program, params, runtimePath, cssPath);
|
|
2498
2559
|
await mkdir2(dirname5(outputPath), { recursive: true });
|
|
2499
2560
|
await writeFile(outputPath, html, "utf-8");
|
|
2500
2561
|
generatedFiles.push(outputPath);
|
|
@@ -2507,13 +2568,13 @@ async function build2(options) {
|
|
|
2507
2568
|
}
|
|
2508
2569
|
} else {
|
|
2509
2570
|
const outputPath = getOutputPath(relPathFromRoutesDir, outDir);
|
|
2510
|
-
const loader = new JsonPageLoader(projectRoot);
|
|
2571
|
+
const loader = new JsonPageLoader(projectRoot, { routesDir: absoluteRoutesDir });
|
|
2511
2572
|
let pageInfo = await loader.loadPage(relPathFromProjectRoot);
|
|
2512
2573
|
if (layoutsDir) {
|
|
2513
2574
|
pageInfo = await processLayouts(pageInfo, layoutsDir);
|
|
2514
2575
|
}
|
|
2515
2576
|
const program = await convertToCompiledProgram(pageInfo);
|
|
2516
|
-
const html = await renderPageToHtml(program, {}, runtimePath);
|
|
2577
|
+
const html = await renderPageToHtml(program, {}, runtimePath, cssPath);
|
|
2517
2578
|
await mkdir2(dirname5(outputPath), { recursive: true });
|
|
2518
2579
|
await writeFile(outputPath, html, "utf-8");
|
|
2519
2580
|
generatedFiles.push(outputPath);
|
|
@@ -2531,12 +2592,12 @@ async function build2(options) {
|
|
|
2531
2592
|
}
|
|
2532
2593
|
|
|
2533
2594
|
// src/config/config-loader.ts
|
|
2534
|
-
import { existsSync as
|
|
2595
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
|
|
2535
2596
|
import { join as join10 } from "path";
|
|
2536
2597
|
var CONFIG_FILENAME = "constela.config.json";
|
|
2537
2598
|
async function loadConfig(projectRoot) {
|
|
2538
2599
|
const configPath = join10(projectRoot, CONFIG_FILENAME);
|
|
2539
|
-
if (!
|
|
2600
|
+
if (!existsSync9(configPath)) {
|
|
2540
2601
|
return {};
|
|
2541
2602
|
}
|
|
2542
2603
|
let content;
|
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/start",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Meta-framework for Constela applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"vite": "^6.0.0",
|
|
43
43
|
"@constela/compiler": "0.7.0",
|
|
44
44
|
"@constela/core": "0.7.0",
|
|
45
|
-
"@constela/router": "8.0.0",
|
|
46
45
|
"@constela/runtime": "0.10.1",
|
|
46
|
+
"@constela/router": "8.0.0",
|
|
47
47
|
"@constela/server": "3.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|