@stati/core 1.3.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +176 -48
- package/dist/core/isg/hash.d.ts.map +1 -1
- package/dist/core/isg/hash.js +13 -1
- package/dist/core/markdown.d.ts.map +1 -1
- package/dist/core/markdown.js +21 -2
- package/dist/core/preview.d.ts +19 -0
- package/dist/core/preview.d.ts.map +1 -0
- package/dist/core/preview.js +159 -0
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +83 -11
- package/dist/core/utils/error-overlay.d.ts +31 -0
- package/dist/core/utils/error-overlay.d.ts.map +1 -0
- package/dist/core/utils/error-overlay.js +562 -0
- package/dist/core/utils/partial-validation.d.ts +6 -0
- package/dist/core/utils/partial-validation.d.ts.map +1 -0
- package/dist/core/utils/partial-validation.js +129 -0
- package/dist/core/utils/server.d.ts +23 -0
- package/dist/core/utils/server.d.ts.map +1 -0
- package/dist/core/utils/server.js +61 -0
- package/dist/core/utils/template-errors.d.ts +28 -0
- package/dist/core/utils/template-errors.d.ts.map +1 -0
- package/dist/core/utils/template-errors.js +128 -0
- package/dist/core/utils/version.d.ts +6 -0
- package/dist/core/utils/version.d.ts.map +1 -0
- package/dist/core/utils/version.js +20 -0
- package/dist/env.d.ts +3 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of attempting to resolve a pretty URL path
|
|
3
|
+
*/
|
|
4
|
+
export interface PrettyUrlResult {
|
|
5
|
+
/** The resolved file path to serve */
|
|
6
|
+
filePath: string | null;
|
|
7
|
+
/** Whether the path was found */
|
|
8
|
+
found: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Attempts to resolve pretty URL paths by trying various fallback strategies.
|
|
12
|
+
* This handles common patterns like:
|
|
13
|
+
* - /path/ -> /path/index.html
|
|
14
|
+
* - /path/ -> /path.html (if no index.html exists)
|
|
15
|
+
* - /path -> /path.html (when original path is not found)
|
|
16
|
+
*
|
|
17
|
+
* @param outDir The output directory to serve files from
|
|
18
|
+
* @param requestPath The requested URL path
|
|
19
|
+
* @param originalFilePath The original file path that was attempted
|
|
20
|
+
* @returns Promise resolving to the file path to serve or null if not found
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolvePrettyUrl(outDir: string, requestPath: string, originalFilePath: string): Promise<PrettyUrlResult>;
|
|
23
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/core/utils/server.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,eAAe,CAAC,CA+C1B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { stat } from 'fs/promises';
|
|
3
|
+
/**
|
|
4
|
+
* Attempts to resolve pretty URL paths by trying various fallback strategies.
|
|
5
|
+
* This handles common patterns like:
|
|
6
|
+
* - /path/ -> /path/index.html
|
|
7
|
+
* - /path/ -> /path.html (if no index.html exists)
|
|
8
|
+
* - /path -> /path.html (when original path is not found)
|
|
9
|
+
*
|
|
10
|
+
* @param outDir The output directory to serve files from
|
|
11
|
+
* @param requestPath The requested URL path
|
|
12
|
+
* @param originalFilePath The original file path that was attempted
|
|
13
|
+
* @returns Promise resolving to the file path to serve or null if not found
|
|
14
|
+
*/
|
|
15
|
+
export async function resolvePrettyUrl(outDir, requestPath, originalFilePath) {
|
|
16
|
+
try {
|
|
17
|
+
const stats = await stat(originalFilePath);
|
|
18
|
+
if (stats.isDirectory()) {
|
|
19
|
+
// Try to serve index.html from directory
|
|
20
|
+
const indexPath = join(originalFilePath, 'index.html');
|
|
21
|
+
try {
|
|
22
|
+
await stat(indexPath);
|
|
23
|
+
return { filePath: indexPath, found: true };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// If no index.html in directory, try to serve corresponding .html file
|
|
27
|
+
// For example: /examples/ -> examples.html
|
|
28
|
+
const directoryName = requestPath.replace(/\/$/, ''); // Remove trailing slash
|
|
29
|
+
const fallbackPath = join(outDir, `${directoryName}.html`);
|
|
30
|
+
try {
|
|
31
|
+
await stat(fallbackPath);
|
|
32
|
+
return { filePath: fallbackPath, found: true };
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { filePath: null, found: false };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// File exists and is not a directory
|
|
40
|
+
return { filePath: originalFilePath, found: true };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// File not found, try fallback strategies for pretty URLs
|
|
44
|
+
if (requestPath.endsWith('/')) {
|
|
45
|
+
// For requests ending with /, try the corresponding .html file
|
|
46
|
+
const pathWithoutSlash = requestPath.slice(0, -1);
|
|
47
|
+
const htmlPath = join(outDir, `${pathWithoutSlash}.html`);
|
|
48
|
+
try {
|
|
49
|
+
const stats = await stat(htmlPath);
|
|
50
|
+
if (stats.isFile()) {
|
|
51
|
+
return { filePath: htmlPath, found: true };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Continue to not found
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// No fallback worked
|
|
59
|
+
return { filePath: null, found: false };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ErrorDetails } from './error-overlay.js';
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced template error that includes file context and suggestions.
|
|
4
|
+
*/
|
|
5
|
+
export declare class TemplateError extends Error {
|
|
6
|
+
readonly filePath?: string;
|
|
7
|
+
readonly line?: number;
|
|
8
|
+
readonly column?: number;
|
|
9
|
+
readonly template?: string;
|
|
10
|
+
readonly context?: {
|
|
11
|
+
before?: string[];
|
|
12
|
+
after?: string[];
|
|
13
|
+
};
|
|
14
|
+
constructor(message: string, filePath?: string, line?: number, column?: number, template?: string);
|
|
15
|
+
/**
|
|
16
|
+
* Converts this template error to ErrorDetails for the overlay.
|
|
17
|
+
*/
|
|
18
|
+
toErrorDetails(): Promise<ErrorDetails>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses Eta template errors to extract file location information.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseEtaError(error: Error, templatePath?: string): TemplateError;
|
|
24
|
+
/**
|
|
25
|
+
* Enhances a generic error with template-specific context.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createTemplateError(error: Error, templatePath?: string, _line?: number, _column?: number): TemplateError;
|
|
28
|
+
//# sourceMappingURL=template-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-errors.d.ts","sourceRoot":"","sources":["../../../src/core/utils/template-errors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChC,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,OAAO,CAAC,EAAE;QACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;gBAGA,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM;IAUnB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,YAAY,CAAC;CAoE9C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,CA8BhF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,YAAY,CAAC,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,CAMf"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { pathExists } from './fs.js';
|
|
3
|
+
/**
|
|
4
|
+
* Enhanced template error that includes file context and suggestions.
|
|
5
|
+
*/
|
|
6
|
+
export class TemplateError extends Error {
|
|
7
|
+
filePath;
|
|
8
|
+
line;
|
|
9
|
+
column;
|
|
10
|
+
template;
|
|
11
|
+
context;
|
|
12
|
+
constructor(message, filePath, line, column, template) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'TemplateError';
|
|
15
|
+
if (filePath !== undefined)
|
|
16
|
+
this.filePath = filePath;
|
|
17
|
+
if (line !== undefined)
|
|
18
|
+
this.line = line;
|
|
19
|
+
if (column !== undefined)
|
|
20
|
+
this.column = column;
|
|
21
|
+
if (template !== undefined)
|
|
22
|
+
this.template = template;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Converts this template error to ErrorDetails for the overlay.
|
|
26
|
+
*/
|
|
27
|
+
async toErrorDetails() {
|
|
28
|
+
const suggestions = [];
|
|
29
|
+
const message = this.message.toLowerCase();
|
|
30
|
+
// Add specific suggestions based on error type
|
|
31
|
+
if (message.includes('not found') || message.includes('cannot resolve')) {
|
|
32
|
+
suggestions.push('Check if the template file exists and has the correct path');
|
|
33
|
+
suggestions.push('Verify the template reference in your layout or include statement');
|
|
34
|
+
suggestions.push('Ensure the template file has the .eta extension');
|
|
35
|
+
}
|
|
36
|
+
else if (message.includes('syntax') || message.includes('unexpected')) {
|
|
37
|
+
suggestions.push('Check for unmatched brackets, quotes, or parentheses');
|
|
38
|
+
suggestions.push('Verify Eta template syntax is correct');
|
|
39
|
+
suggestions.push('Look for unclosed template tags');
|
|
40
|
+
}
|
|
41
|
+
else if (message.includes('undefined') || message.includes('null')) {
|
|
42
|
+
suggestions.push('Check if all required data is available in template context');
|
|
43
|
+
suggestions.push('Add conditional checks for optional template variables');
|
|
44
|
+
suggestions.push('Verify page frontMatter and data structure');
|
|
45
|
+
}
|
|
46
|
+
// Try to read file context if available
|
|
47
|
+
let context;
|
|
48
|
+
let code;
|
|
49
|
+
if (this.filePath && this.line && (await pathExists(this.filePath))) {
|
|
50
|
+
try {
|
|
51
|
+
const fileContent = await readFile(this.filePath, 'utf-8');
|
|
52
|
+
const lines = fileContent.split('\n');
|
|
53
|
+
const errorLineIndex = this.line - 1;
|
|
54
|
+
if (errorLineIndex >= 0 && errorLineIndex < lines.length) {
|
|
55
|
+
code = lines[errorLineIndex];
|
|
56
|
+
// Get surrounding context
|
|
57
|
+
const contextLines = 3;
|
|
58
|
+
const beforeLines = lines.slice(Math.max(0, errorLineIndex - contextLines), errorLineIndex);
|
|
59
|
+
const afterLines = lines.slice(errorLineIndex + 1, Math.min(lines.length, errorLineIndex + contextLines + 1));
|
|
60
|
+
context = {
|
|
61
|
+
before: beforeLines,
|
|
62
|
+
after: afterLines,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Ignore file read errors
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const errorDetails = {
|
|
71
|
+
type: 'template',
|
|
72
|
+
message: this.message,
|
|
73
|
+
suggestions,
|
|
74
|
+
};
|
|
75
|
+
if (this.stack !== undefined)
|
|
76
|
+
errorDetails.stack = this.stack;
|
|
77
|
+
if (this.filePath !== undefined)
|
|
78
|
+
errorDetails.file = this.filePath;
|
|
79
|
+
if (this.line !== undefined)
|
|
80
|
+
errorDetails.line = this.line;
|
|
81
|
+
if (this.column !== undefined)
|
|
82
|
+
errorDetails.column = this.column;
|
|
83
|
+
if (code !== undefined)
|
|
84
|
+
errorDetails.code = code;
|
|
85
|
+
if (context !== undefined)
|
|
86
|
+
errorDetails.context = context;
|
|
87
|
+
return errorDetails;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parses Eta template errors to extract file location information.
|
|
92
|
+
*/
|
|
93
|
+
export function parseEtaError(error, templatePath) {
|
|
94
|
+
let filePath = templatePath;
|
|
95
|
+
let line;
|
|
96
|
+
let column;
|
|
97
|
+
// Try to parse error location from Eta error messages
|
|
98
|
+
const message = error.message;
|
|
99
|
+
// Eta syntax errors often include line/column info
|
|
100
|
+
const locationMatch = message.match(/at line (\d+), column (\d+)/i);
|
|
101
|
+
if (locationMatch && locationMatch[1] && locationMatch[2]) {
|
|
102
|
+
line = parseInt(locationMatch[1], 10);
|
|
103
|
+
column = parseInt(locationMatch[2], 10);
|
|
104
|
+
}
|
|
105
|
+
// Try to extract file path from stack trace if not provided
|
|
106
|
+
if (!filePath && error.stack) {
|
|
107
|
+
const stackLines = error.stack.split('\n');
|
|
108
|
+
for (const stackLine of stackLines) {
|
|
109
|
+
const fileMatch = stackLine.match(/at.*\(([^)]+\.eta):(\d+):(\d+)\)/);
|
|
110
|
+
if (fileMatch && fileMatch[1] && fileMatch[2] && fileMatch[3]) {
|
|
111
|
+
filePath = fileMatch[1];
|
|
112
|
+
line = parseInt(fileMatch[2], 10);
|
|
113
|
+
column = parseInt(fileMatch[3], 10);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return new TemplateError(message, filePath, line, column);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Enhances a generic error with template-specific context.
|
|
122
|
+
*/
|
|
123
|
+
export function createTemplateError(error, templatePath, _line, _column) {
|
|
124
|
+
if (error instanceof TemplateError) {
|
|
125
|
+
return error;
|
|
126
|
+
}
|
|
127
|
+
return parseEtaError(error, templatePath);
|
|
128
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/core/utils/version.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAWxC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
/**
|
|
5
|
+
* Gets the current version of Stati core from package.json
|
|
6
|
+
* @returns The version string
|
|
7
|
+
*/
|
|
8
|
+
export function getStatiVersion() {
|
|
9
|
+
try {
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const packageJsonPath = join(__dirname, '../../package.json');
|
|
13
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
14
|
+
return packageJson.version;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Fallback for cases where package.json can't be read
|
|
18
|
+
return '1.0.0';
|
|
19
|
+
}
|
|
20
|
+
}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,QAEhE;AAED,wBAAgB,MAAM,WAErB"}
|
package/dist/env.js
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -22,11 +22,14 @@
|
|
|
22
22
|
export type { StatiConfig, PageModel, FrontMatter, BuildContext, PageContext, BuildHooks, NavNode, ISGConfig, AgingRule, BuildStats, } from './types/index.js';
|
|
23
23
|
export type { BuildOptions } from './core/build.js';
|
|
24
24
|
export type { DevServerOptions } from './core/dev.js';
|
|
25
|
+
export type { PreviewServerOptions } from './core/preview.js';
|
|
25
26
|
export type { InvalidationResult } from './core/invalidate.js';
|
|
26
27
|
export { build } from './core/build.js';
|
|
27
28
|
export { createDevServer } from './core/dev.js';
|
|
29
|
+
export { createPreviewServer } from './core/preview.js';
|
|
28
30
|
export { loadConfig } from './config/loader.js';
|
|
29
31
|
export { invalidate } from './core/invalidate.js';
|
|
32
|
+
export { setEnv, getEnv } from './env.js';
|
|
30
33
|
import type { StatiConfig } from './types/index.js';
|
|
31
34
|
/**
|
|
32
35
|
* Helper function for defining Stati configuration with TypeScript IntelliSense.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
|
package/dist/index.js
CHANGED
|
@@ -21,8 +21,10 @@
|
|
|
21
21
|
*/
|
|
22
22
|
export { build } from './core/build.js';
|
|
23
23
|
export { createDevServer } from './core/dev.js';
|
|
24
|
+
export { createPreviewServer } from './core/preview.js';
|
|
24
25
|
export { loadConfig } from './config/loader.js';
|
|
25
26
|
export { invalidate } from './core/invalidate.js';
|
|
27
|
+
export { setEnv, getEnv } from './env.js';
|
|
26
28
|
/**
|
|
27
29
|
* Helper function for defining Stati configuration with TypeScript IntelliSense.
|
|
28
30
|
* Provides type checking and autocompletion for configuration options.
|