Automatically create shortlinks for your Astro site
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: initial shortlinks implementation

+94
+69
src/index.ts
··· 1 + import type { AstroConfig, AstroIntegration } from "astro"; 2 + import type { 3 + Shortlinker, 4 + AstroShortlinkOptions, 5 + PageMapping, 6 + } from "./types.js"; 7 + 8 + export * from "./types.js"; 9 + export * from "./chhoto-url.js"; 10 + export * from "./worker-links.js"; 11 + 12 + export default function createIntegration( 13 + shortlinker: Shortlinker, 14 + options: AstroShortlinkOptions 15 + ): AstroIntegration { 16 + let config: AstroConfig; 17 + 18 + return { 19 + name: "astro-shortlinks", 20 + hooks: { 21 + "astro:config:done": async ({ config: cfg }) => { 22 + config = cfg; 23 + }, 24 + "astro:build:done": async ({ pages, logger }) => { 25 + if (!config.site) 26 + return logger.error( 27 + "The `site` Astro config option is required but has not been set. Cannot create any shortlinks." 28 + ); 29 + 30 + const siteRoot = new URL(config.base, config.site); 31 + const pageUrls = pages.map((p) => new URL(p.pathname, siteRoot)); 32 + let pageMappings: PageMapping[]; 33 + 34 + try { 35 + pageMappings = await options.getPageMapping(pageUrls); 36 + } catch (err) { 37 + return logger.error(`Error while getting page mapping: ${err}`); 38 + } 39 + 40 + if (!pageMappings.length) 41 + return logger.warn("Empty page mapping generated, skipping."); 42 + 43 + // TODO: warn and return if there are duplicates in list 44 + 45 + logger.info(`Creating shortlinks through ${shortlinker.name}`); 46 + 47 + try { 48 + const shortlinkerLogger = logger.fork( 49 + `astro-shortlinks/${shortlinker.name}` 50 + ); 51 + const succeeded = await shortlinker.run( 52 + pageMappings, 53 + shortlinkerLogger 54 + ); 55 + 56 + if (succeeded !== false) { 57 + logger.info( 58 + `Successfully created ${pageMappings.length} shortlinks!` 59 + ); 60 + } 61 + } catch (err) { 62 + logger.error( 63 + `Error while creating shortlinks with ${shortlinker.name}: ${err}` 64 + ); 65 + } 66 + }, 67 + }, 68 + }; 69 + }
+25
src/types.ts
··· 1 + import type { AstroIntegrationLogger } from "astro"; 2 + 3 + type Promisable<T> = Promise<T> | T; 4 + /** A simple record describing the full `longlink` a `shortlink` will be pointing to. */ 5 + export type PageMapping = { longlink: string; shortlink: string }; 6 + 7 + export interface AstroShortlinkOptions { 8 + getPageMapping(pages: URL[]): Promisable<PageMapping[]>; 9 + } 10 + 11 + export interface Shortlinker { 12 + /** 13 + * The name of the shortlinker instance. 14 + * Should usually be the name of the service the shortlinker is made for. 15 + */ 16 + name: string; 17 + /** 18 + * Function to run the shortlinker over a set of {@link PageMapping}s. 19 + * `logger` is an Astro logger that is namespaced to the shortlinker. 20 + */ 21 + run( 22 + mappings: PageMapping[], 23 + logger: AstroIntegrationLogger 24 + ): Promise<void | boolean>; 25 + }