feat(storage-fs): adapt to the new storage option and rename the package
This commit is contained in:
parent
8e87ade5c0
commit
7d8ac9b185
8 changed files with 52 additions and 41 deletions
94
packages/storage-fs/src/index.ts
Normal file
94
packages/storage-fs/src/index.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { type EmigrateStorage, type MigrationStatus } from '@emigrate/plugin-tools/types';
|
||||
|
||||
export type StorageFsOptions = {
|
||||
filename: string;
|
||||
};
|
||||
|
||||
type SerializedError = {
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
export default function storageFs({ filename }: StorageFsOptions): EmigrateStorage {
|
||||
const filePath = path.resolve(process.cwd(), filename);
|
||||
const lockFilePath = `${filePath}.lock`;
|
||||
|
||||
const read = async (): Promise<
|
||||
Record<string, { status: MigrationStatus; date: string; error?: SerializedError }>
|
||||
> => {
|
||||
try {
|
||||
const contents = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return JSON.parse(contents);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
let lastUpdate: Promise<void> = Promise.resolve();
|
||||
|
||||
const update = async (migration: string, status: MigrationStatus, error?: Error) => {
|
||||
lastUpdate = lastUpdate.then(async () => {
|
||||
const history = await read();
|
||||
|
||||
const newHistory = {
|
||||
...history,
|
||||
[migration]: {
|
||||
status,
|
||||
date: new Date().toISOString(),
|
||||
error: error ? { name: error.name, message: error.message, stack: error.stack } : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
await fs.writeFile(filePath, JSON.stringify(newHistory, undefined, 2));
|
||||
});
|
||||
|
||||
return lastUpdate;
|
||||
};
|
||||
|
||||
return {
|
||||
async initializeStorage() {
|
||||
return {
|
||||
async lock(migrations) {
|
||||
try {
|
||||
const fd = await fs.open(lockFilePath, 'wx');
|
||||
|
||||
await fd.close();
|
||||
|
||||
return migrations;
|
||||
} catch {
|
||||
throw new Error('Could not acquire file lock for migrations');
|
||||
}
|
||||
},
|
||||
async unlock() {
|
||||
try {
|
||||
await fs.unlink(lockFilePath);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
},
|
||||
async *getHistory() {
|
||||
const history = await read();
|
||||
|
||||
yield* Object.entries(history).map(([name, { status, date, error }]) => ({
|
||||
name,
|
||||
status,
|
||||
error,
|
||||
date: new Date(date),
|
||||
}));
|
||||
},
|
||||
async onSuccess(migration) {
|
||||
await update(migration.name, 'done');
|
||||
},
|
||||
async onError(migration, error) {
|
||||
await update(migration.name, 'failed', error);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue