@stati/core 1.2.0 â 1.3.1
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/core/build.d.ts +20 -16
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +22 -16
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +27 -18
- package/dist/core/isg/build-lock.d.ts.map +1 -1
- package/dist/core/isg/build-lock.js +4 -2
- package/package.json +1 -1
package/dist/core/build.d.ts
CHANGED
|
@@ -28,31 +28,35 @@ export interface BuildOptions {
|
|
|
28
28
|
version?: string;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Builds the
|
|
32
|
-
*
|
|
31
|
+
* Builds the Stati site with ISG support.
|
|
32
|
+
* Processes all pages and assets, with smart caching for incremental builds.
|
|
33
|
+
*
|
|
33
34
|
* Uses build locking to prevent concurrent builds from corrupting cache.
|
|
35
|
+
* The manifest tracks build dependencies and cache entries for efficient rebuilds.
|
|
36
|
+
* Pages are only rebuilt if their content, templates, or dependencies have changed.
|
|
37
|
+
*
|
|
38
|
+
* Build process:
|
|
39
|
+
* 1. Load configuration and content
|
|
40
|
+
* 2. Check cache manifest for existing entries
|
|
41
|
+
* 3. Process each page (rebuild only if needed)
|
|
42
|
+
* 4. Copy static assets
|
|
43
|
+
* 5. Update cache manifest
|
|
34
44
|
*
|
|
35
45
|
* @param options - Build configuration options
|
|
46
|
+
* @returns Promise resolving to build statistics
|
|
47
|
+
* @throws {Error} When configuration is invalid
|
|
48
|
+
* @throws {Error} When template rendering fails
|
|
49
|
+
* @throws {Error} When build lock cannot be acquired
|
|
36
50
|
*
|
|
37
51
|
* @example
|
|
38
52
|
* ```typescript
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* // Basic build
|
|
42
|
-
* await build();
|
|
43
|
-
*
|
|
44
|
-
* // Build with options
|
|
45
|
-
* await build({
|
|
46
|
-
* clean: true,
|
|
53
|
+
* const stats = await build({
|
|
47
54
|
* force: true,
|
|
48
|
-
*
|
|
55
|
+
* clean: true,
|
|
56
|
+
* includeDrafts: false
|
|
49
57
|
* });
|
|
58
|
+
* console.log(`Built ${stats.pageCount} pages in ${stats.buildTime}ms`);
|
|
50
59
|
* ```
|
|
51
|
-
*
|
|
52
|
-
* @throws {Error} When configuration loading fails
|
|
53
|
-
* @throws {Error} When content processing fails
|
|
54
|
-
* @throws {Error} When template rendering fails
|
|
55
|
-
* @throws {Error} When build lock cannot be acquired
|
|
56
60
|
*/
|
|
57
61
|
export declare function build(options?: BuildOptions): Promise<BuildStats>;
|
|
58
62
|
//# sourceMappingURL=build.d.ts.map
|
package/dist/core/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2HD
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAW3E"}
|
package/dist/core/build.js
CHANGED
|
@@ -112,34 +112,40 @@ function formatBuildStats(stats) {
|
|
|
112
112
|
return output;
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
* Builds the
|
|
116
|
-
*
|
|
115
|
+
* Builds the Stati site with ISG support.
|
|
116
|
+
* Processes all pages and assets, with smart caching for incremental builds.
|
|
117
|
+
*
|
|
117
118
|
* Uses build locking to prevent concurrent builds from corrupting cache.
|
|
119
|
+
* The manifest tracks build dependencies and cache entries for efficient rebuilds.
|
|
120
|
+
* Pages are only rebuilt if their content, templates, or dependencies have changed.
|
|
121
|
+
*
|
|
122
|
+
* Build process:
|
|
123
|
+
* 1. Load configuration and content
|
|
124
|
+
* 2. Check cache manifest for existing entries
|
|
125
|
+
* 3. Process each page (rebuild only if needed)
|
|
126
|
+
* 4. Copy static assets
|
|
127
|
+
* 5. Update cache manifest
|
|
118
128
|
*
|
|
119
129
|
* @param options - Build configuration options
|
|
130
|
+
* @returns Promise resolving to build statistics
|
|
131
|
+
* @throws {Error} When configuration is invalid
|
|
132
|
+
* @throws {Error} When template rendering fails
|
|
133
|
+
* @throws {Error} When build lock cannot be acquired
|
|
120
134
|
*
|
|
121
135
|
* @example
|
|
122
136
|
* ```typescript
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* // Basic build
|
|
126
|
-
* await build();
|
|
127
|
-
*
|
|
128
|
-
* // Build with options
|
|
129
|
-
* await build({
|
|
130
|
-
* clean: true,
|
|
137
|
+
* const stats = await build({
|
|
131
138
|
* force: true,
|
|
132
|
-
*
|
|
139
|
+
* clean: true,
|
|
140
|
+
* includeDrafts: false
|
|
133
141
|
* });
|
|
142
|
+
* console.log(`Built ${stats.pageCount} pages in ${stats.buildTime}ms`);
|
|
134
143
|
* ```
|
|
135
|
-
*
|
|
136
|
-
* @throws {Error} When configuration loading fails
|
|
137
|
-
* @throws {Error} When content processing fails
|
|
138
|
-
* @throws {Error} When template rendering fails
|
|
139
|
-
* @throws {Error} When build lock cannot be acquired
|
|
140
144
|
*/
|
|
141
145
|
export async function build(options = {}) {
|
|
142
146
|
const cacheDir = join(process.cwd(), '.stati');
|
|
147
|
+
// Ensure cache directory exists before acquiring build lock
|
|
148
|
+
await ensureDir(cacheDir);
|
|
143
149
|
// Use build lock to prevent concurrent builds, with force option to override
|
|
144
150
|
return await withBuildLock(cacheDir, () => buildInternal(options), {
|
|
145
151
|
force: Boolean(options.force || options.clean), // Allow force if user explicitly requests it
|
package/dist/core/dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,aAAa,CAAC;AAMvD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,aAAa,CAAC;AAMvD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAoaxF"}
|
package/dist/core/dev.js
CHANGED
|
@@ -71,17 +71,30 @@ export async function createDevServer(options = {}) {
|
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
isBuilding = true;
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
// Create a quiet logger for dev builds that suppresses verbose output
|
|
76
|
+
const devLogger = {
|
|
77
|
+
info: () => { }, // Suppress info messages
|
|
78
|
+
success: () => { }, // Suppress success messages
|
|
79
|
+
error: logger.error || (() => { }),
|
|
80
|
+
warning: logger.warning || (() => { }),
|
|
81
|
+
building: () => { }, // Suppress building messages
|
|
82
|
+
processing: () => { }, // Suppress processing messages
|
|
83
|
+
stats: () => { }, // Suppress stats messages
|
|
84
|
+
};
|
|
74
85
|
try {
|
|
86
|
+
const relativePath = changedPath
|
|
87
|
+
.replace(process.cwd(), '')
|
|
88
|
+
.replace(/\\/g, '/')
|
|
89
|
+
.replace(/^\//, '');
|
|
75
90
|
// Check if the changed file is a template/partial
|
|
76
91
|
if (changedPath.endsWith('.eta') || changedPath.includes('_partials')) {
|
|
77
|
-
|
|
78
|
-
await handleTemplateChange(changedPath);
|
|
92
|
+
await handleTemplateChange(changedPath, devLogger);
|
|
79
93
|
}
|
|
80
94
|
else {
|
|
81
95
|
// Content or static file changed - use normal rebuild
|
|
82
|
-
logger.info?.(`đ Content changed: ${changedPath}`);
|
|
83
96
|
await build({
|
|
84
|
-
logger,
|
|
97
|
+
logger: devLogger,
|
|
85
98
|
force: false,
|
|
86
99
|
clean: false,
|
|
87
100
|
...(configPath && { configPath }),
|
|
@@ -97,10 +110,12 @@ export async function createDevServer(options = {}) {
|
|
|
97
110
|
}
|
|
98
111
|
});
|
|
99
112
|
}
|
|
100
|
-
|
|
113
|
+
const duration = Date.now() - startTime;
|
|
114
|
+
logger.info?.(`⥠${relativePath} rebuilt in ${duration}ms`);
|
|
101
115
|
}
|
|
102
116
|
catch (error) {
|
|
103
|
-
|
|
117
|
+
const duration = Date.now() - startTime;
|
|
118
|
+
logger.error?.(`â Rebuild failed after ${duration}ms: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
119
|
}
|
|
105
120
|
finally {
|
|
106
121
|
isBuilding = false;
|
|
@@ -109,16 +124,16 @@ export async function createDevServer(options = {}) {
|
|
|
109
124
|
/**
|
|
110
125
|
* Handles template/partial file changes by invalidating affected pages
|
|
111
126
|
*/
|
|
112
|
-
async function handleTemplateChange(templatePath) {
|
|
127
|
+
async function handleTemplateChange(templatePath, buildLogger) {
|
|
113
128
|
const cacheDir = join(process.cwd(), '.stati');
|
|
129
|
+
const effectiveLogger = buildLogger || logger;
|
|
114
130
|
try {
|
|
115
131
|
// Load existing cache manifest
|
|
116
132
|
let cacheManifest = await loadCacheManifest(cacheDir);
|
|
117
133
|
if (!cacheManifest) {
|
|
118
134
|
// No cache exists, perform full rebuild
|
|
119
|
-
logger.info?.('No cache found, performing full rebuild...');
|
|
120
135
|
await build({
|
|
121
|
-
logger,
|
|
136
|
+
logger: effectiveLogger,
|
|
122
137
|
force: false,
|
|
123
138
|
clean: false,
|
|
124
139
|
...(configPath && { configPath }),
|
|
@@ -135,27 +150,21 @@ export async function createDevServer(options = {}) {
|
|
|
135
150
|
}
|
|
136
151
|
}
|
|
137
152
|
if (affectedPages.length > 0) {
|
|
138
|
-
logger.info?.(`đ¯ Invalidating ${affectedPages.length} affected pages:`);
|
|
139
|
-
affectedPages.forEach((page) => logger.info?.(` đ ${page}`));
|
|
140
153
|
// Save updated cache manifest
|
|
141
154
|
await saveCacheManifest(cacheDir, cacheManifest);
|
|
142
155
|
// Perform incremental rebuild (only affected pages will be rebuilt)
|
|
143
156
|
await build({
|
|
144
|
-
logger,
|
|
157
|
+
logger: effectiveLogger,
|
|
145
158
|
force: false,
|
|
146
159
|
clean: false,
|
|
147
160
|
...(configPath && { configPath }),
|
|
148
161
|
});
|
|
149
162
|
}
|
|
150
|
-
else {
|
|
151
|
-
logger.info?.('âšī¸ No pages affected by template change');
|
|
152
|
-
}
|
|
153
163
|
}
|
|
154
|
-
catch
|
|
155
|
-
logger.warning?.(`Template dependency analysis failed, performing full rebuild: ${error instanceof Error ? error.message : String(error)}`);
|
|
164
|
+
catch {
|
|
156
165
|
// Fallback to full rebuild
|
|
157
166
|
await build({
|
|
158
|
-
logger,
|
|
167
|
+
logger: effectiveLogger,
|
|
159
168
|
force: false,
|
|
160
169
|
clean: false,
|
|
161
170
|
...(configPath && { configPath }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-lock.d.ts","sourceRoot":"","sources":["../../../src/core/isg/build-lock.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B;;;;;;;;;;;;;;;;;;;OAmBG;IACG,WAAW,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDrF;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBlC;;;;;;;;;;;OAWG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAiBpC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAY9C;;;OAGG;YACW,eAAe;IAQ7B;;OAEG;YACW,cAAc;
|
|
1
|
+
{"version":3,"file":"build-lock.d.ts","sourceRoot":"","sources":["../../../src/core/isg/build-lock.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B;;;;;;;;;;;;;;;;;;;OAmBG;IACG,WAAW,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDrF;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBlC;;;;;;;;;;;OAWG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAiBpC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAY9C;;;OAGG;YACW,eAAe;IAQ7B;;OAEG;YACW,cAAc;IAc5B;;OAEG;YACW,YAAY;IAS1B;;OAEG;YACW,gBAAgB;IAY9B;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,OAAO,CAAC,CAAC,CAAC,CASZ"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fse from 'fs-extra';
|
|
2
|
-
const { writeFile, readFile, pathExists, remove } = fse;
|
|
3
|
-
import { join } from 'path';
|
|
2
|
+
const { writeFile, readFile, pathExists, remove, ensureDir } = fse;
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
4
|
import { hostname } from 'os';
|
|
5
5
|
/**
|
|
6
6
|
* Manages build process locking to prevent concurrent Stati builds from corrupting cache.
|
|
@@ -167,6 +167,8 @@ export class BuildLockManager {
|
|
|
167
167
|
timestamp: new Date().toISOString(),
|
|
168
168
|
hostname: this.getHostname(),
|
|
169
169
|
};
|
|
170
|
+
// Ensure the cache directory exists before creating the lock file
|
|
171
|
+
await ensureDir(dirname(this.lockPath));
|
|
170
172
|
// Use 'wx' flag to create file exclusively (fails if exists)
|
|
171
173
|
await writeFile(this.lockPath, JSON.stringify(lockInfo, null, 2), { flag: 'wx' });
|
|
172
174
|
}
|