full site update
This commit is contained in:
151
node_modules/astro/dist/content/mutable-data-store.js
generated
vendored
151
node_modules/astro/dist/content/mutable-data-store.js
generated
vendored
@@ -1,19 +1,22 @@
|
||||
import { promises as fs, existsSync } from "node:fs";
|
||||
import { existsSync, promises as fs } from "node:fs";
|
||||
import * as devalue from "devalue";
|
||||
import { Traverse } from "neotraverse/modern";
|
||||
import { imageSrcToImportId, importIdToSymbolName } from "../assets/utils/resolveImports.js";
|
||||
import { AstroError, AstroErrorData } from "../core/errors/index.js";
|
||||
import { IMAGE_IMPORT_PREFIX } from "./consts.js";
|
||||
import { DataStore } from "./data-store.js";
|
||||
import { ImmutableDataStore } from "./data-store.js";
|
||||
import { contentModuleToId } from "./utils.js";
|
||||
const SAVE_DEBOUNCE_MS = 500;
|
||||
class MutableDataStore extends DataStore {
|
||||
const MAX_DEPTH = 10;
|
||||
class MutableDataStore extends ImmutableDataStore {
|
||||
#file;
|
||||
#assetsFile;
|
||||
#modulesFile;
|
||||
#saveTimeout;
|
||||
#assetsSaveTimeout;
|
||||
#modulesSaveTimeout;
|
||||
#savePromise;
|
||||
#savePromiseResolve;
|
||||
#dirty = false;
|
||||
#assetsDirty = false;
|
||||
#modulesDirty = false;
|
||||
@@ -61,7 +64,7 @@ class MutableDataStore extends DataStore {
|
||||
this.#assetsFile = filePath;
|
||||
if (this.#assetImports.size === 0) {
|
||||
try {
|
||||
await fs.writeFile(filePath, "export default new Map();");
|
||||
await this.#writeFileAtomic(filePath, "export default new Map();");
|
||||
} catch (err) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
||||
}
|
||||
@@ -73,7 +76,7 @@ class MutableDataStore extends DataStore {
|
||||
const exports = [];
|
||||
this.#assetImports.forEach((id) => {
|
||||
const symbol = importIdToSymbolName(id);
|
||||
imports.push(`import ${symbol} from '${id}';`);
|
||||
imports.push(`import ${symbol} from ${JSON.stringify(id)};`);
|
||||
exports.push(`[${JSON.stringify(id)}, ${symbol}]`);
|
||||
});
|
||||
const code = (
|
||||
@@ -84,7 +87,7 @@ export default new Map([${exports.join(", ")}]);
|
||||
`
|
||||
);
|
||||
try {
|
||||
await fs.writeFile(filePath, code);
|
||||
await this.#writeFileAtomic(filePath, code);
|
||||
} catch (err) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
||||
}
|
||||
@@ -94,7 +97,7 @@ export default new Map([${exports.join(", ")}]);
|
||||
this.#modulesFile = filePath;
|
||||
if (this.#moduleImports.size === 0) {
|
||||
try {
|
||||
await fs.writeFile(filePath, "export default new Map();");
|
||||
await this.#writeFileAtomic(filePath, "export default new Map();");
|
||||
} catch (err) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
||||
}
|
||||
@@ -104,28 +107,41 @@ export default new Map([${exports.join(", ")}]);
|
||||
}
|
||||
const lines = [];
|
||||
for (const [fileName, specifier] of this.#moduleImports) {
|
||||
lines.push(`['${fileName}', () => import('${specifier}')]`);
|
||||
lines.push(`[${JSON.stringify(fileName)}, () => import(${JSON.stringify(specifier)})]`);
|
||||
}
|
||||
const code = `
|
||||
export default new Map([
|
||||
${lines.join(",\n")}]);
|
||||
`;
|
||||
try {
|
||||
await fs.writeFile(filePath, code);
|
||||
await this.#writeFileAtomic(filePath, code);
|
||||
} catch (err) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
||||
}
|
||||
this.#modulesDirty = false;
|
||||
}
|
||||
#maybeResolveSavePromise() {
|
||||
if (!this.#saveTimeout && !this.#assetsSaveTimeout && !this.#modulesSaveTimeout && this.#savePromiseResolve) {
|
||||
this.#savePromiseResolve();
|
||||
this.#savePromiseResolve = void 0;
|
||||
this.#savePromise = void 0;
|
||||
}
|
||||
}
|
||||
#writeAssetsImportsDebounced() {
|
||||
this.#assetsDirty = true;
|
||||
if (this.#assetsFile) {
|
||||
if (this.#assetsSaveTimeout) {
|
||||
clearTimeout(this.#assetsSaveTimeout);
|
||||
}
|
||||
this.#assetsSaveTimeout = setTimeout(() => {
|
||||
if (!this.#savePromise) {
|
||||
this.#savePromise = new Promise((resolve) => {
|
||||
this.#savePromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
this.#assetsSaveTimeout = setTimeout(async () => {
|
||||
this.#assetsSaveTimeout = void 0;
|
||||
this.writeAssetImports(this.#assetsFile);
|
||||
await this.writeAssetImports(this.#assetsFile);
|
||||
this.#maybeResolveSavePromise();
|
||||
}, SAVE_DEBOUNCE_MS);
|
||||
}
|
||||
}
|
||||
@@ -135,22 +151,73 @@ ${lines.join(",\n")}]);
|
||||
if (this.#modulesSaveTimeout) {
|
||||
clearTimeout(this.#modulesSaveTimeout);
|
||||
}
|
||||
this.#modulesSaveTimeout = setTimeout(() => {
|
||||
if (!this.#savePromise) {
|
||||
this.#savePromise = new Promise((resolve) => {
|
||||
this.#savePromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
this.#modulesSaveTimeout = setTimeout(async () => {
|
||||
this.#modulesSaveTimeout = void 0;
|
||||
this.writeModuleImports(this.#modulesFile);
|
||||
await this.writeModuleImports(this.#modulesFile);
|
||||
this.#maybeResolveSavePromise();
|
||||
}, SAVE_DEBOUNCE_MS);
|
||||
}
|
||||
}
|
||||
// Skips the debounce and writes to disk immediately
|
||||
async #saveToDiskNow() {
|
||||
if (this.#saveTimeout) {
|
||||
clearTimeout(this.#saveTimeout);
|
||||
}
|
||||
this.#saveTimeout = void 0;
|
||||
if (this.#file) {
|
||||
await this.writeToDisk();
|
||||
}
|
||||
this.#maybeResolveSavePromise();
|
||||
}
|
||||
#saveToDiskDebounced() {
|
||||
this.#dirty = true;
|
||||
if (this.#file) {
|
||||
if (this.#saveTimeout) {
|
||||
clearTimeout(this.#saveTimeout);
|
||||
if (this.#saveTimeout) {
|
||||
clearTimeout(this.#saveTimeout);
|
||||
}
|
||||
if (!this.#savePromise) {
|
||||
this.#savePromise = new Promise((resolve) => {
|
||||
this.#savePromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
this.#saveTimeout = setTimeout(async () => {
|
||||
this.#saveTimeout = void 0;
|
||||
if (this.#file) {
|
||||
await this.writeToDisk();
|
||||
}
|
||||
this.#maybeResolveSavePromise();
|
||||
}, SAVE_DEBOUNCE_MS);
|
||||
}
|
||||
#writing = /* @__PURE__ */ new Set();
|
||||
#pending = /* @__PURE__ */ new Set();
|
||||
async #writeFileAtomic(filePath, data, depth = 0) {
|
||||
if (depth > MAX_DEPTH) {
|
||||
return;
|
||||
}
|
||||
const fileKey = filePath.toString();
|
||||
if (this.#writing.has(fileKey)) {
|
||||
this.#pending.add(fileKey);
|
||||
return;
|
||||
}
|
||||
this.#writing.add(fileKey);
|
||||
const tempFile = filePath instanceof URL ? new URL(`${filePath.href}.tmp`) : `${filePath}.tmp`;
|
||||
try {
|
||||
const oldData = await fs.readFile(filePath, "utf-8").catch(() => "");
|
||||
if (oldData === data) {
|
||||
return;
|
||||
}
|
||||
await fs.writeFile(tempFile, data);
|
||||
await fs.rename(tempFile, filePath);
|
||||
} finally {
|
||||
this.#writing.delete(fileKey);
|
||||
if (this.#pending.has(fileKey)) {
|
||||
this.#pending.delete(fileKey);
|
||||
await this.#writeFileAtomic(filePath, data, depth + 1);
|
||||
}
|
||||
this.#saveTimeout = setTimeout(() => {
|
||||
this.#saveTimeout = void 0;
|
||||
this.writeToDisk(this.#file);
|
||||
}, SAVE_DEBOUNCE_MS);
|
||||
}
|
||||
}
|
||||
scopedStore(collectionName) {
|
||||
@@ -159,7 +226,17 @@ ${lines.join(",\n")}]);
|
||||
entries: () => this.entries(collectionName),
|
||||
values: () => this.values(collectionName),
|
||||
keys: () => this.keys(collectionName),
|
||||
set: ({ id: key, data, body, filePath, deferredRender, digest, rendered, assetImports }) => {
|
||||
set: ({
|
||||
id: key,
|
||||
data,
|
||||
body,
|
||||
filePath,
|
||||
deferredRender,
|
||||
digest,
|
||||
rendered,
|
||||
assetImports,
|
||||
legacyId
|
||||
}) => {
|
||||
if (!key) {
|
||||
throw new Error(`ID must be a non-empty string`);
|
||||
}
|
||||
@@ -200,6 +277,9 @@ ${lines.join(",\n")}]);
|
||||
if (rendered) {
|
||||
entry.rendered = rendered;
|
||||
}
|
||||
if (legacyId) {
|
||||
entry.legacyId = legacyId;
|
||||
}
|
||||
if (deferredRender) {
|
||||
entry.deferredRender = deferredRender;
|
||||
if (filePath) {
|
||||
@@ -229,17 +309,30 @@ ${lines.join(",\n")}]);
|
||||
has: (key) => this.has(collectionKey, key)
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Returns a promise that resolves when all pending saves are complete.
|
||||
* This includes any in-progress debounced saves for the data store, asset imports, and module imports.
|
||||
*/
|
||||
async waitUntilSaveComplete() {
|
||||
if (!this.#savePromise) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
await this.#saveToDiskNow();
|
||||
return this.#savePromise;
|
||||
}
|
||||
toString() {
|
||||
return devalue.stringify(this._collections);
|
||||
}
|
||||
async writeToDisk(filePath) {
|
||||
async writeToDisk() {
|
||||
if (!this.#dirty) {
|
||||
return;
|
||||
}
|
||||
if (!this.#file) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError);
|
||||
}
|
||||
try {
|
||||
await fs.writeFile(filePath, this.toString());
|
||||
this.#file = filePath;
|
||||
this.#dirty = false;
|
||||
await this.#writeFileAtomic(this.#file, this.toString());
|
||||
} catch (err) {
|
||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
||||
}
|
||||
@@ -270,11 +363,17 @@ ${lines.join(",\n")}]);
|
||||
try {
|
||||
if (existsSync(filePath)) {
|
||||
const data = await fs.readFile(filePath, "utf-8");
|
||||
return MutableDataStore.fromString(data);
|
||||
const store2 = await MutableDataStore.fromString(data);
|
||||
store2.#file = filePath;
|
||||
return store2;
|
||||
} else {
|
||||
await fs.mkdir(new URL("./", filePath), { recursive: true });
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
return new MutableDataStore();
|
||||
const store = new MutableDataStore();
|
||||
store.#file = filePath;
|
||||
return store;
|
||||
}
|
||||
}
|
||||
export {
|
||||
|
Reference in New Issue
Block a user