Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Support custom clone operation #12

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ const ignoreFormat = createFormat({
const unique = (array) => Array.from(new Set() < T[number] > array).sort()
await fs.writeFile(resolvedPath, unique(expected).join('\n'), 'utf8')
},
// Optional: define a 'clone' function to control how the result of 'read' is cloned before being passed to 'update'
// Defaults to `structuredClone`[1] if available, otherwise `v8.deserialize(v8.serialize(obj))`.
clone(actual) {
return myCustomClone(actual)
},
})

export default async (_workspaceDir) => {
Expand Down
22 changes: 13 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ type UpdateError =

export async function performUpdates<
FileNameWithOptions extends string,
UserDefinedFormatPlugins extends BaseFormatPlugins
UserDefinedFormatPlugins extends BaseFormatPlugins,
>(
workspaceDir: string,
updateParam:
| UpdateOptionsLegacy<FileNameWithOptions>
| UpdateOptions<FileNameWithOptions>
| UpdateOptionsWithFormats<FileNameWithOptions, UserDefinedFormatPlugins>,
opts?: { test?: boolean }
opts?: { test?: boolean },
): Promise<null | UpdateError[]> {
const update = 'files' in updateParam ? updateParam : { files: updateParam }
let pkgs = await findWorkspacePackagesNoCheck(workspaceDir)
Expand All @@ -88,7 +88,11 @@ export async function performUpdates<
_writeProjectManifest: writeProjectManifest,
}
const actual = (await fileExists(resolvedPath)) ? await formatPlugin.read(formatHandlerOptions) : null
const expected = await formatPlugin.update(clone(actual), updateFile as any, formatHandlerOptions)
const expected = await formatPlugin.update(
formatPlugin.clone ? formatPlugin.clone(actual, formatHandlerOptions) : clone(actual),
b0o marked this conversation as resolved.
Show resolved Hide resolved
updateFile as any,
formatHandlerOptions,
)
const equal =
(actual == null && expected == null) ||
(actual != null && expected != null && (await formatPlugin.equal(expected, actual, formatHandlerOptions)))
Expand All @@ -107,8 +111,8 @@ export async function performUpdates<

errors.push({ actual, expected, path: resolvedPath })
} catch (error) {
const errorMessage = `Error while processing ${resolvedPath}: ${error.message}`;
errors.push({ exception: errorMessage });
const errorMessage = `Error while processing ${resolvedPath}: ${error.message}`
errors.push({ exception: errorMessage })
}
}
}
Expand All @@ -120,7 +124,7 @@ function printJsonDiff(actual: unknown, expected: unknown, out: NodeJS.WriteStre
printDiff(
typeof actual !== 'string' ? JSON.stringify(actual, null, 2) : actual,
typeof expected !== 'string' ? JSON.stringify(expected, null, 2) : expected,
out
out,
)
}

Expand All @@ -141,7 +145,7 @@ function parseFileKey(fileKey: string, formatPlugins: Record<string, FormatPlugi

if (!formatPlugin) {
throw new Error(
`Configuration error: there is no format plugin for fileKey "${fileKey}" with explicit format specifier "${extension}"`
`Configuration error: there is no format plugin for fileKey "${fileKey}" with explicit format specifier "${extension}"`,
)
}

Expand All @@ -156,8 +160,8 @@ function parseFileKey(fileKey: string, formatPlugins: Record<string, FormatPlugi
if (!extension) {
throw new Error(
`Configuration error: there is no format plugin for fileKey "${fileKey}", supported extensions are ${Object.keys(
formatPlugins
)}`
formatPlugins,
)}`,
)
}

Expand Down
9 changes: 8 additions & 1 deletion src/updater/formatPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@ export interface FormatPlugin<Content> {
update(
actual: Content | null,
updater: Updater<Content>,
options: FormatPluginFnOptions
options: FormatPluginFnOptions,
): PromiseOrValue<Content | null>

/** Called only if check for equality is required (`actual != null` & `expected != null`) */
equal(expected: Content, actual: Content, options: FormatPluginFnOptions): PromiseOrValue<boolean>

/** Called only if write is required (`--test` isn't specified, `expected != null` and `expected` is not equal to `actual`) */
write(expected: Content, options: FormatPluginFnOptions): PromiseOrValue<void>

/**
* Used to clone the object returned by `read` before passing it to `update`.
* Defaults to `structuredClone`[1] if available, otherwise `v8.deserialize(v8.serialize(obj))`.
* [1]: https://developer.mozilla.org/en-US/docs/web/api/structuredclone
*/
clone?(value: Content, options: FormatPluginFnOptions): Content
}

export interface FormatPluginFnOptions {
Expand Down
Loading