feat(plugin-tools): improve error serialization and let each storage plugin serialize errors themselves
This commit is contained in:
parent
09181f284d
commit
a79f8e8e37
6 changed files with 29 additions and 10 deletions
5
.changeset/fast-olives-bathe.md
Normal file
5
.changeset/fast-olives-bathe.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@emigrate/plugin-tools': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
When serializing errors take all "own properties" into account to be able to serialize errors thrown by the `mysql2` package for instance without losing any information
|
||||||
8
.changeset/few-hounds-retire.md
Normal file
8
.changeset/few-hounds-retire.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
'@emigrate/plugin-tools': patch
|
||||||
|
'@emigrate/storage-fs': patch
|
||||||
|
'@emigrate/mysql': patch
|
||||||
|
'@emigrate/cli': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Serialization of errors now happens inside storage plugins because it makes more sense and the types are easier to work with this way
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
type GenerateMigrationFunction,
|
type GenerateMigrationFunction,
|
||||||
type GeneratorPlugin,
|
type GeneratorPlugin,
|
||||||
} from '@emigrate/plugin-tools/types';
|
} from '@emigrate/plugin-tools/types';
|
||||||
import { getTimestampPrefix, sanitizeMigrationName } from '@emigrate/plugin-tools';
|
import { getTimestampPrefix, sanitizeMigrationName, serializeError } from '@emigrate/plugin-tools';
|
||||||
|
|
||||||
const defaultTable = 'migrations';
|
const defaultTable = 'migrations';
|
||||||
|
|
||||||
|
|
@ -213,7 +213,7 @@ export const createMysqlStorage = ({ table = defaultTable, connection }: MysqlSt
|
||||||
status: row.status,
|
status: row.status,
|
||||||
date: new Date(row.date),
|
date: new Date(row.date),
|
||||||
// FIXME: Migrate the migrations table to support the error column
|
// FIXME: Migrate the migrations table to support the error column
|
||||||
error: row.status === 'failed' ? new Error('Unknown error reason') : undefined,
|
error: row.status === 'failed' ? serializeError(new Error('Unknown error reason')) : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,16 @@ import {
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
|
|
||||||
export const serializeError = (error: Error): SerializedError => {
|
export const serializeError = (error: Error): SerializedError => {
|
||||||
return {
|
const properties: Record<string, unknown> = {
|
||||||
name: error.name,
|
name: error.name,
|
||||||
message: error.message,
|
|
||||||
stack: error.stack,
|
|
||||||
cause: error.cause instanceof Error ? serializeError(error.cause) : error.cause,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (const key of Object.getOwnPropertyNames(error)) {
|
||||||
|
const value = error[key as keyof Error];
|
||||||
|
properties[key] = value instanceof Error ? serializeError(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties as SerializedError;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isGeneratorPlugin = (plugin: any): plugin is GeneratorPlugin => {
|
export const isGeneratorPlugin = (plugin: any): plugin is GeneratorPlugin => {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ export type StringOrModule<T> = string | T | (() => Awaitable<T>) | (() => Await
|
||||||
export type MigrationStatus = 'failed' | 'done' | 'pending';
|
export type MigrationStatus = 'failed' | 'done' | 'pending';
|
||||||
|
|
||||||
export type SerializedError = {
|
export type SerializedError = {
|
||||||
name: string;
|
[key: string]: unknown;
|
||||||
|
name?: string;
|
||||||
message: string;
|
message: string;
|
||||||
stack?: string;
|
stack?: string;
|
||||||
cause?: unknown;
|
cause?: unknown;
|
||||||
|
|
@ -73,7 +74,7 @@ export type Storage = {
|
||||||
* @param migration The name of the migration that should be marked as failed.
|
* @param migration The name of the migration that should be marked as failed.
|
||||||
* @param error The error that caused the migration to fail.
|
* @param error The error that caused the migration to fail.
|
||||||
*/
|
*/
|
||||||
onError(migration: MigrationMetadataFinished, error: SerializedError): Promise<void>;
|
onError(migration: MigrationMetadataFinished, error: Error): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Called when the command is finished or aborted (e.g. by a SIGTERM or SIGINT signal).
|
* Called when the command is finished or aborted (e.g. by a SIGTERM or SIGINT signal).
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import fs from 'node:fs/promises';
|
import fs from 'node:fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
|
import { serializeError } from '@emigrate/plugin-tools';
|
||||||
import { type SerializedError, type EmigrateStorage, type MigrationStatus } from '@emigrate/plugin-tools/types';
|
import { type SerializedError, type EmigrateStorage, type MigrationStatus } from '@emigrate/plugin-tools/types';
|
||||||
|
|
||||||
export type StorageFsOptions = {
|
export type StorageFsOptions = {
|
||||||
|
|
@ -26,7 +27,7 @@ export default function storageFs({ filename }: StorageFsOptions): EmigrateStora
|
||||||
|
|
||||||
let lastUpdate: Promise<void> = Promise.resolve();
|
let lastUpdate: Promise<void> = Promise.resolve();
|
||||||
|
|
||||||
const update = async (migration: string, status: MigrationStatus, error?: SerializedError) => {
|
const update = async (migration: string, status: MigrationStatus, error?: Error) => {
|
||||||
lastUpdate = lastUpdate.then(async () => {
|
lastUpdate = lastUpdate.then(async () => {
|
||||||
const history = await read();
|
const history = await read();
|
||||||
|
|
||||||
|
|
@ -35,7 +36,7 @@ export default function storageFs({ filename }: StorageFsOptions): EmigrateStora
|
||||||
[migration]: {
|
[migration]: {
|
||||||
status,
|
status,
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
error,
|
error: error ? serializeError(error) : undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue