Skip to content

Commit 5441f0d

Browse files
committed
better opt dependency handling
1 parent 75e55bd commit 5441f0d

File tree

7 files changed

+111
-17
lines changed

7 files changed

+111
-17
lines changed

.changeset/many-brooms-lay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@bluecadet/launchpad-content": patch
3+
---
4+
5+
Better optional dependency handling, with more descriptive error messages

package-lock.json

Lines changed: 24 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/content/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
"homepage": "https://github.com/bluecadet/launchpad/packages/content",
3030
"dependencies": {
3131
"@bluecadet/launchpad-utils": "~2.0.1",
32-
"@portabletext/to-html": "2.0.0",
33-
"@sanity/block-content-to-markdown": "^0.0.5",
3432
"chalk": "^5.0.0",
3533
"glob": "^11.0.0",
3634
"jsonpath-plus": "^10.3.0",
@@ -43,13 +41,21 @@
4341
"zod": "^3.23.8"
4442
},
4543
"peerDependencies": {
44+
"@portabletext/to-html": "2.0.0",
45+
"@sanity/block-content-to-markdown": "^0.0.5",
4646
"@sanity/client": "^6.4.9",
4747
"@sanity/image-url": "^1.1.0",
4848
"airtable": "^0.11.1",
4949
"contentful": "^9.0.0",
5050
"sharp": "^0.33.5"
5151
},
5252
"peerDependenciesMeta": {
53+
"@portabletext/to-html": {
54+
"optional": true
55+
},
56+
"@sanity/block-content-to-markdown": {
57+
"optional": true
58+
},
5359
"@sanity/client": {
5460
"optional": true
5561
},
@@ -69,6 +75,8 @@
6975
"devDependencies": {
7076
"@bluecadet/launchpad-testing": "0.1.0",
7177
"@bluecadet/launchpad-tsconfig": "0.1.0",
78+
"@portabletext/to-html": "2.0.0",
79+
"@sanity/block-content-to-markdown": "^0.0.5",
7280
"@sanity/client": "^6.4.9",
7381
"@sanity/image-url": "^1.1.0",
7482
"@types/markdown-it": "^14.1.2",

packages/content/src/plugins/sanity-image-url-transform.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import imageUrlBuilder from "@sanity/image-url";
21
import type { ImageUrlBuilder } from "@sanity/image-url/lib/types/builder.js";
32
import type {
43
SanityAsset,
@@ -36,6 +35,19 @@ const sanityImageUrlTransformSchema = z.object({
3635
.describe("Function to build the image URL"),
3736
});
3837

38+
39+
function tryImportSanityImage() {
40+
try {
41+
return import("@sanity/image-url");
42+
} catch (e) {
43+
throw new Error(
44+
'Could not find peer dependency "@sanity/image-url". Make sure you have installed it.',
45+
{ cause: e },
46+
);
47+
}
48+
}
49+
50+
3951
export default function sanityImageUrlTransform(
4052
options: z.input<typeof sanityImageUrlTransformSchema>,
4153
) {
@@ -45,12 +57,15 @@ export default function sanityImageUrlTransform(
4557
options,
4658
);
4759

48-
const builder = imageUrlBuilder(rest);
49-
5060
return defineContentPlugin({
5161
name: "sanity-to-html",
5262
hooks: {
5363
async onContentFetchDone(ctx) {
64+
65+
const { default: imageUrlBuilder } = await tryImportSanityImage();
66+
67+
const builder = imageUrlBuilder(rest);
68+
5469
let transformCount = 0;
5570

5671
ctx.logger.info("Transforming URLs using Sanity Image URL Transform...");

packages/content/src/plugins/sanity-to-html.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { toHTML } from "@portabletext/to-html";
2-
31
import { z } from "zod";
42
import { defineContentPlugin } from "../content-plugin-driver.js";
53
import { applyTransformToFiles, isBlockContent } from "../utils/content-transform-utils.js";
@@ -13,13 +11,29 @@ const sanityToHtmlSchema = z.object({
1311
keys: dataKeysSchema.optional(),
1412
});
1513

14+
15+
function tryImportPortableText() {
16+
try {
17+
return import("@portabletext/to-html");
18+
} catch (e) {
19+
throw new Error(
20+
'Could not find peer dependency "@portabletext/to-html". Make sure you have installed it.',
21+
{ cause: e },
22+
);
23+
}
24+
}
25+
26+
1627
export default function sanityToHtml(options: z.input<typeof sanityToHtmlSchema>) {
1728
const { path, keys } = parsePluginConfig("sanityToHtml", sanityToHtmlSchema, options);
1829

1930
return defineContentPlugin({
2031
name: "sanity-to-html",
2132
hooks: {
2233
async onContentFetchDone(ctx) {
34+
35+
const { toHTML } = await tryImportPortableText();
36+
2337
let transformCount = 0;
2438
ctx.logger.info("Transforming sanity blocks to HTML...");
2539

packages/content/src/plugins/sanity-to-markdown.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// @ts-expect-error - no types from this lib
2-
import toMarkdown from "@sanity/block-content-to-markdown";
1+
32
import { z } from "zod";
43
import { defineContentPlugin } from "../content-plugin-driver.js";
54
import { applyTransformToFiles, isBlockContent } from "../utils/content-transform-utils.js";
@@ -13,13 +12,29 @@ const sanityToMdSchema = z.object({
1312
keys: dataKeysSchema.optional(),
1413
});
1514

15+
16+
function tryImportBlockToMd() {
17+
try {
18+
// @ts-expect-error - no types from this lib
19+
return import("@sanity/block-content-to-markdown");
20+
} catch (e) {
21+
throw new Error(
22+
'Could not find peer dependency "@sanity/block-content-to-markdown". Make sure you have installed it.',
23+
{ cause: e },
24+
);
25+
}
26+
}
27+
28+
1629
export default function sanityToMd(options: z.input<typeof sanityToMdSchema>) {
1730
const { path, keys } = parsePluginConfig("sanityToMd", sanityToMdSchema, options);
1831

1932
return defineContentPlugin({
2033
name: "sanity-to-markdown",
2134
hooks: {
2235
async onContentFetchDone(ctx) {
36+
const { toMarkdown } = await tryImportBlockToMd();
37+
2338
let transformCount = 0;
2439
ctx.logger.info("Transforming sanity blocks to markdown...");
2540

packages/content/src/plugins/sharp.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import path from "node:path";
33
import { pipeline } from "node:stream/promises";
44
import chalk from "chalk";
55
import PQueue from "p-queue";
6-
import Sharp from "sharp";
6+
import type SharpType from "sharp";
77
import { z } from "zod";
88
import { defineContentPlugin } from "../content-plugin-driver.js";
99
import { getMatchingDocuments, regexToJSONPathQuery } from "../utils/content-transform-utils.js";
@@ -38,15 +38,29 @@ const sharpPluginSchema = z.object({
3838
.describe("Update URLs in the content to point to the transformed images"),
3939
/** The sharp transform to apply to the images. */
4040
buildTransform: z
41-
.function(z.tuple([z.custom<Sharp.Sharp>()]))
42-
.returns(z.custom<Sharp.Sharp>())
41+
.function(z.tuple([z.custom<SharpType.Sharp>()]))
42+
.returns(z.custom<SharpType.Sharp>())
4343
.describe("The sharp transform to apply to the images."),
4444
/** The number of images to transform concurrently. Defaults to 4. */
4545
concurrency: z.number().default(4).describe("The number of images to transform concurrently."),
4646
});
4747

48+
49+
50+
function tryImportSharp() {
51+
try {
52+
return import("sharp");
53+
} catch (e) {
54+
throw new Error(
55+
'Could not find peer dependency "sharp". Make sure you have installed it.',
56+
{ cause: e },
57+
);
58+
}
59+
}
60+
61+
4862
async function transformImage(
49-
sharpTransform: Sharp.Sharp,
63+
sharpTransform: SharpType.Sharp,
5064
sourceImagePath: string,
5165
outputImagePath: string,
5266
backupImagePath: string,
@@ -101,6 +115,8 @@ export default function sharp(options: z.input<typeof sharpPluginSchema>) {
101115
name: "sharp",
102116
hooks: {
103117
async onContentFetchDone(ctx) {
118+
const { default: Sharp } = await tryImportSharp();
119+
104120
const matchingDocuments = getMatchingDocuments(ctx.data, resolvedConfig.keys);
105121

106122
if (matchingDocuments.isErr()) {
@@ -208,7 +224,7 @@ export default function sharp(options: z.input<typeof sharpPluginSchema>) {
208224
});
209225
}
210226

211-
function getOutputFilename(inputPath: string, sharpTransform: Sharp.Sharp) {
227+
function getOutputFilename(inputPath: string, sharpTransform: SharpType.Sharp) {
212228
const { dir, name, ext } = path.parse(inputPath);
213229

214230
// 'options' is a private property, so we need to use Object.getOwnPropertyDescriptor

0 commit comments

Comments
 (0)