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

fix!: Simplify emitted declarations for plugins #104

Merged
merged 7 commits into from
Apr 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
41 changes: 41 additions & 0 deletions .changeset/witty-poems-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
"astro-integration-kit": minor
---

Simplifies emitted declarations for plugins.

This avoids problems with too complex or non-portable types for published libraries offering plugins. Previously a simple plugin would result in a declaration like this:

```ts
declare const hookProviderPlugin: astro_integration_kit.Plugin<"hook-provider", {
'astro:config:setup': ({ config }: {
config: astro.AstroConfig;
command: "dev" | "build" | "preview";
isRestart: boolean;
updateConfig: (newConfig: DeepPartial<astro.AstroConfig>) => astro.AstroConfig;
addRenderer: (renderer: astro.AstroRenderer) => void;
addWatchFile: (path: string | URL) => void;
injectScript: (stage: astro.InjectedScriptStage, content: string) => void;
injectRoute: (injectRoute: astro.InjectedRoute) => void;
addClientDirective: (directive: astro.ClientDirectiveConfig) => void;
addDevOverlayPlugin: (entrypoint: string) => void;
addDevToolbarApp: (entrypoint: string | astro.DevToolbarAppEntry) => void;
addMiddleware: (mid: astro.AstroIntegrationMiddleware) => void;
logger: astro.AstroIntegrationLogger;
}) => {
doThing: (thing: string) => void;
};
};
```

Now, the same plugin will emit the following simplified declaration, without inlining any of the AstroHooks types:

```ts
declare const hookProviderPlugin: astro_integration_kit.Plugin<"hook-provider", {
'astro:config:setup': {
doThing: (thing: string) => void;
};
};
```

As shown above, this simplification also removes the unneeded re-declaration of the plugin hook input, which is a breaking change if you are declaring your generic explicitly.
2 changes: 0 additions & 2 deletions docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export default defineConfig({
{
label: "hmrIntegration",
link: "/dev/hmr-integration/",
badge: badge("new"),
},
],
},
Expand Down Expand Up @@ -168,7 +167,6 @@ export default defineConfig({
{
label: "watchDirectory",
link: "/utilities/watch-directory/",
badge: badge("new"),
},
{
label: "watchIntegration",
Expand Down
24 changes: 24 additions & 0 deletions docs/src/content/docs/getting-started/upgrade-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ import { Tabs, TabItem } from '@astrojs/starlight/components';

Features get added and removed, and breaking changes are introduced! This documents how to migrate.

## `0.13.0`

---

### `Plugin` type simplified

The new Plugin signature added back in [`0.9.0`](#new-plugin-signature-and-defineplugin) returned the need for emitted declarations to include the full type for hook parameters from Astro (which was removed on [`0.7.0`](#plugins-types)).
This was added along with support for a plugin to define new utilities for multiple hooks at once.

Now, the Plugin generics have been simplified again to allow for such support without having to replicate Astro's hook parameters types. Just like in `0.7.0`, this should be non-breaking for any plugin relying on type inference but plugins with explicitly declared signatures need to update the following:

```ts del={5} ins={6}
type SomePlugin = Plugin<
"utilityName",
"astro:config:setup",
{
"astro:config:setup": (HookParameters<"astro:config:setup">) => {
"astro:config:setup": {
utilityName: (params: UtilityParams) => UtilityOutput
}
}
>;
```

## `0.12.0`

---
Expand Down
22 changes: 10 additions & 12 deletions package/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ import type { DevToolbarApp } from "astro";
import type { Prettify } from "../internal/types.js";

export type PluginHooksConstraint = {
[Hook in keyof Hooks]?: (
...args: Parameters<Hooks[Hook]>
) => Record<string, unknown>;
[Hook in keyof Hooks]?: Record<string, unknown>;
};

type PluginPerHookSetup<THooks extends PluginHooksConstraint> = {
[Hook in keyof THooks & keyof Hooks]: (...params: Parameters<Hooks[Hook]>) => THooks[Hook];
};

export type Plugin<
TName extends string,
THooks extends PluginHooksConstraint,
> = {
name: TName;
setup: (params: { name: string }) => THooks;
setup: (params: { name: string }) => PluginPerHookSetup<THooks>;
};

// To avoid having to call this manually for every generic
export type AnyPlugin = Plugin<string, Record<string, unknown>>;
export type AnyPlugin = Plugin<string, Record<string, any>>;

declare global {
namespace AstroIntegrationKit {
Expand All @@ -41,13 +43,9 @@ type AnyFunction = (...args: Array<any>) => any;
*/
type SimplifyPlugin<TPlugin extends AnyPlugin = AnyPlugin> = {
name: TPlugin["name"];
hooks: {
[K in keyof ReturnType<TPlugin["setup"]>]: ReturnType<
TPlugin["setup"]
>[K] extends AnyFunction
? ReturnType<ReturnType<TPlugin["setup"]>[K]>
: never;
};
hooks: TPlugin extends Plugin<any, infer THooks>
? THooks
: Record<string, never>,
};

/**
Expand Down
Loading