@coreframe/scripts 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/assets.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Plugin } from "vite";
2
-
3
1
  //#region assets.d.ts
4
2
  type AssetManifest = Record<string, AssetManifestEntry>;
5
3
  type AssetManifestEntry = {
@@ -83,9 +81,9 @@ type CheckAssetsOptions = AssetWorkflowOptions & {
83
81
  type PublishAssetsOptions = AssetWorkflowOptions & {
84
82
  outputDir?: string;
85
83
  };
86
- type CoreframeAssetsPluginOptions = {
87
- devMaterialize?: boolean;
88
- cwd?: string;
84
+ type LoadedAssetManifest = {
85
+ manifest: AssetManifest;
86
+ problems: AssetProblem[];
89
87
  };
90
88
  declare function addAsset({
91
89
  alt,
@@ -109,10 +107,8 @@ declare function publishAssets({
109
107
  outputDir
110
108
  }?: PublishAssetsOptions): Promise<AssetPublishResult>;
111
109
  declare function materializeAsset(assetId: string, options?: BuildAssetsOptions): Promise<AssetBuildResult>;
112
- declare function coreframeAssetsPlugin({
113
- cwd,
114
- devMaterialize
115
- }?: CoreframeAssetsPluginOptions): Plugin;
116
110
  declare function printAssetResult(result: unknown, json?: boolean): void;
111
+ declare function readAssetManifest(cwd?: string): Promise<LoadedAssetManifest>;
112
+ declare function formatAssetProblems(problems: AssetProblem[]): string;
117
113
  //#endregion
118
- export { AddAssetOptions, AssetBuildEntry, AssetBuildResult, AssetManifest, AssetManifestEntry, AssetProblem, AssetPublishResult, AssetStatus, AssetStatusEntry, AssetVariant, AssetVariantStatus, AssetWorkflowOptions, BuildAssetsOptions, CheckAssetsOptions, CoreframeAssetsPluginOptions, PublishAssetsOptions, PublishedAsset, addAsset, buildAssets, checkAssets, coreframeAssetsPlugin, materializeAsset, printAssetResult, publishAssets };
114
+ export { AddAssetOptions, AssetBuildEntry, AssetBuildResult, AssetManifest, AssetManifestEntry, AssetProblem, AssetPublishResult, AssetStatus, AssetStatusEntry, AssetVariant, AssetVariantStatus, AssetWorkflowOptions, BuildAssetsOptions, CheckAssetsOptions, LoadedAssetManifest, PublishAssetsOptions, PublishedAsset, addAsset, buildAssets, checkAssets, formatAssetProblems, materializeAsset, printAssetResult, publishAssets, readAssetManifest };
package/dist/assets.js CHANGED
@@ -1,4 +1,3 @@
1
- import{createHash as e}from"node:crypto";import{copyFile as t,mkdir as n,readFile as r,stat as i,writeFile as a}from"node:fs/promises";import{dirname as o,extname as s,join as c,relative as l,resolve as u,sep as d}from"node:path";import f from"nano-spawn";const p=`assets-src`,m=c(`assets`,`manifest.json`),h=/^[a-z0-9]+(?:[/-][a-z0-9]+)*$/,g=/@asset\s+([a-z0-9][a-z0-9/-]*)/g,_=/^version https:\/\/git-lfs.github.com\/spec\/v1\n/m;async function v({alt:e,cwd:r=process.cwd(),file:i,id:a}){T(a);let s=k(a,i),c=u(r,s),l=u(r,i);await n(o(c),{recursive:!0}),await t(l,c),await N(r,s);let d=await E(r),f=await j(c);return d.manifest[a]={source:s,alt:e,width:f.width,height:f.height,variants:[]},await D(r,d.manifest),y({cwd:r,id:a,pull:!1})}async function y({cwd:e=process.cwd(),id:t,pull:n=!0,updateManifest:r=!0}={}){let{manifest:i,problems:a}=await E(e),o=[],s=[];for(let[r,c]of Object.entries(i)){if(t&&r!==t)continue;let l=u(e,c.source);if(!await z(l)){a.push(B(r,c.source));continue}if(await I(l)&&(n&&(await P(e,c.source),o.push(c.source)),await I(l))){a.push({code:`SOURCE_POINTER_MISSING_OBJECT`,message:`Source asset "${c.source}" is still a Git LFS pointer after a targeted pull.`,assetId:r,file:c.source,fix:`Run: git lfs pull --include="${c.source}"`});continue}let d=await A(e,r,c);i[r]={...c,variants:[d]},s.push({assetId:r,variants:[d]})}return t&&!i[t]&&a.push({code:`REFERENCE_MISSING`,message:`Asset "${t}" is not present in ${m}.`,assetId:t,fix:`Run: coreframe assets add <file> --id ${t} --alt "..."`}),r&&a.length===0&&s.length>0&&await D(e,i),{ok:a.length===0,assets:s,fetched:o,problems:a}}async function b({cwd:e=process.cwd(),fix:t=!1}={}){if(t){let t=await y({cwd:e}),n=await b({cwd:e,fix:!1});return{...n,ok:n.ok&&t.ok,problems:[...n.problems,...t.problems]}}let n=await E(e),r=[...n.problems],i=[],a=await L(e);for(let[a,o]of Object.entries(n.manifest)){h.test(a)||r.push({code:`INVALID_ASSET_ID`,message:`Asset ID "${a}" must use lowercase path segments.`,assetId:a}),o.alt.trim()||r.push({code:`INVALID_ALT`,message:`Asset "${a}" is missing alt text.`,assetId:a,file:o.source,fix:`Run: coreframe assets add ${o.source} --id ${a} --alt "..."`}),o.source.startsWith(`${p}/`)||r.push({code:`INVALID_SOURCE_PATH`,message:`Asset "${a}" source must be under ${p}/.`,assetId:a,file:o.source});let n=await z(u(e,o.source)),s=n?await F(e,o.source):!1;n?s||r.push({code:`LFS_NOT_TRACKED`,message:`Source asset "${o.source}" is not tracked by Git LFS.`,assetId:a,file:o.source,fix:`Run: git lfs track "${o.source}" && git add .gitattributes ${o.source}`}):r.push(B(a,o.source));let c=await Promise.all(o.variants.map(async t=>({...t,exists:await z(u(e,t.path))})));(o.variants.length===0||c.some(e=>!e.exists))&&r.push({code:`GENERATED_VARIANT_MISSING`,message:`Asset "${a}" is missing generated variants.`,assetId:a,file:o.source,fix:t?void 0:`Run: coreframe assets build --id ${a}`}),i.push({assetId:a,source:o.source,sourceExists:n,lfsTracked:s,variants:c})}for(let e of a)n.manifest[e.assetId]||r.push({code:`INVALID_REFERENCE`,message:`Asset reference "${e.assetId}" is not present in ${m}.`,assetId:e.assetId,file:e.file,fix:`Run: coreframe assets add <file> --id ${e.assetId} --alt "..."`});return{ok:r.length===0,assets:i,problems:r}}async function x({cwd:e=process.cwd(),env:r=process.env,outputDir:i}={}){let s=[...(await b({cwd:e})).problems],l=[],d=[],f=u(e,i??r.COREFRAME_ASSETS_PUBLISH_DIR??`release-upload/assets`),p=c(f,`asset-publish-report.json`);if(s.length===0){let{manifest:r}=await E(e);for(let[i,a]of Object.entries(r))for(let r of a.variants){let a=u(e,r.path),s=c(f,r.path),p={assetId:i,source:r.path,target:s,size:r.size};if(await z(s)){d.push(p);continue}await n(o(s),{recursive:!0}),await t(a,s),l.push(p)}}let m={ok:s.length===0,uploaded:l,skipped:d,reportPath:p,problems:s};return await n(o(p),{recursive:!0}),await a(p,`${JSON.stringify(m,null,2)}\n`),m}async function S(e,t={}){return y({...t,id:e})}function C({cwd:e=process.cwd(),devMaterialize:t=!0}={}){let n=`virtual:assets`,r=`\0${n}`;return{name:`coreframe:assets`,async buildStart(){if(this.meta.watchMode)return;let t=await b({cwd:e});if(!t.ok)throw Error(V(t.problems))},async resolveId(e){if(e===n)return r},async load(t){if(t!==r)return;let{manifest:n,problems:i}=await E(e);if(i.length>0)throw Error(V(i));return[`const manifest = ${JSON.stringify(n)};`,`export { manifest };`,`export function asset(id) {`,` const entry = manifest[id];`," if (!entry) throw new Error(`Unknown Coreframe asset: ${id}`);",` return entry;`,`}`].join(`
2
- `)},async transform(n,r){let i=[...n.matchAll(g)].map(e=>e[1]);if(i.length===0)return;let a=await E(e),o=[...a.problems],s=n;for(let n of i){let i=a.manifest[n];if(!i){o.push({code:`INVALID_REFERENCE`,message:`Asset reference "${n}" in "${r}" is not present in ${m}.`,assetId:n,file:r});continue}if(this.meta.watchMode&&t&&i.variants.length===0){this.warn(`Materializing Coreframe asset "${n}" for dev.`);let t=await S(n,{cwd:e,updateManifest:!1});o.push(...t.problems);let r=t.assets.find(e=>e.assetId===n);r&&(a.manifest[n]={...i,variants:r.variants})}let c=a.manifest[n]?.variants[0];if(!c){o.push({code:`GENERATED_VARIANT_MISSING`,message:`Asset "${n}" has no generated variant.`,assetId:n,file:r,fix:`Run: coreframe assets build --id ${n}`});continue}s=s.replaceAll(`@asset ${n}`,`/${c.path}`)}if(o.length>0)throw Error(V(o));return s}}}function w(e,t=!1){if(t){console.log(JSON.stringify(e,null,2));return}let n=e;n.problems&&n.problems.length>0&&console.error(V(n.problems)),console.log(n.ok===!1?`Asset workflow has problems.`:`Asset workflow complete.`)}function T(e){if(!h.test(e))throw Error(`Asset ID "${e}" must use lowercase path segments.`)}async function E(e){let t=u(e,m);if(!await z(t))return{manifest:{},problems:[{code:`MANIFEST_MISSING`,message:`${m} does not exist.`,file:m,fix:`Run: coreframe assets add <file> --id <asset-id> --alt "..."`}]};try{return{manifest:JSON.parse(await r(t,`utf8`)),problems:[]}}catch(e){return{manifest:{},problems:[{code:`INVALID_MANIFEST`,message:`${m} is not valid JSON: ${e.message}`,file:m}]}}}async function D(e,t){let r=u(e,m);await n(o(r),{recursive:!0}),await a(r,`${JSON.stringify(O(t),null,2)}\n`)}function O(e){return Object.fromEntries(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)))}function k(e,t){return c(p,`${e}${s(t).toLowerCase()}`).split(d).join(`/`)}async function A(t,r,i){let s=await M(),l=u(t,i.source),d=Math.min(i.width,1200),f=c(`.coreframe/assets`,r),p=await s(l).resize({width:d,withoutEnlargement:!0}).webp().toBuffer(),m=e(`sha256`).update(p).digest(`hex`).slice(0,12),h=`${f}.${m}.${d}.webp`,g=u(t,h);await n(o(g),{recursive:!0}),await a(g,p);let _=await s(p).metadata();return{format:`webp`,width:_.width??d,height:_.height??Math.round(i.height/i.width*d),path:h,size:p.byteLength,hash:m}}async function j(e){let t=await(await M())(e).metadata();if(!t.width||!t.height)throw Error(`Could not read dimensions for ${e}.`);return{width:t.width,height:t.height}}async function M(){try{return(await import(`sharp`)).default}catch{throw Error(`The assets workflow requires the optional sharp dependency.`)}}async function N(e,t){await f(`git`,[`lfs`,`track`,t],{cwd:e})}async function P(e,t){await f(`git`,[`lfs`,`pull`,`--include=${t}`],{cwd:e})}async function F(e,t){try{return(await f(`git`,[`check-attr`,`filter`,`--`,t],{cwd:e})).stdout.includes(`filter: lfs`)}catch{return!1}}async function I(e){try{let t=await r(e,`utf8`);return _.test(t)}catch{return!1}}async function L(e){let t=await R(e),n=[];for(let i of t){let t=await r(u(e,i),`utf8`);for(let e of t.matchAll(g))n.push({assetId:e[1],file:i})}return n}async function R(e){return(await f(`git`,[`ls-files`,`*.md`,`*.mdx`,`*.ts`,`*.tsx`],{cwd:e})).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).filter(e=>!e.startsWith(`dist/`))}async function z(e){try{return await i(e),!0}catch{return!1}}function B(e,t){return{code:`SOURCE_MISSING`,message:`Source asset "${t}" does not exist.`,assetId:e,file:t,fix:`Run: coreframe assets add <file> --id ${e} --alt "..."`}}function V(e){return e.map(e=>[`${e.code}: ${e.message}`,e.file?` file: ${l(process.cwd(),u(e.file))}`:void 0,e.fix?` fix: ${e.fix}`:void 0].filter(Boolean).join(`
1
+ import{createHash as e}from"node:crypto";import{copyFile as t,mkdir as n,readFile as r,stat as i,writeFile as a}from"node:fs/promises";import{dirname as o,extname as s,join as c,relative as l,resolve as u,sep as d}from"node:path";import f from"nano-spawn";const p=`assets-src`,m=c(`assets`,`manifest.json`),h=/^[a-z0-9]+(?:[/-][a-z0-9]+)*$/,g=/@asset\s+([a-z0-9][a-z0-9/-]*)/g,_=/^version https:\/\/git-lfs.github.com\/spec\/v1\n/m;async function v({alt:e,cwd:r=process.cwd(),file:i,id:a}){w(a);let s=O(a,i),c=u(r,s),l=u(r,i);await n(o(c),{recursive:!0}),await t(l,c),await M(r,s);let d=await T(r),f=await A(c);return d.manifest[a]={source:s,alt:e,width:f.width,height:f.height,variants:[]},await E(r,d.manifest),y({cwd:r,id:a,pull:!1})}async function y({cwd:e=process.cwd(),id:t,pull:n=!0,updateManifest:r=!0}={}){let{manifest:i,problems:a}=await T(e),o=[],s=[];for(let[r,c]of Object.entries(i)){if(t&&r!==t)continue;let l=u(e,c.source);if(!await R(l)){a.push(z(r,c.source));continue}if(await F(l)&&(n&&(await N(e,c.source),o.push(c.source)),await F(l))){a.push({code:`SOURCE_POINTER_MISSING_OBJECT`,message:`Source asset "${c.source}" is still a Git LFS pointer after a targeted pull.`,assetId:r,file:c.source,fix:`Run: git lfs pull --include="${c.source}"`});continue}let d=await k(e,r,c);i[r]={...c,variants:[d]},s.push({assetId:r,variants:[d]})}return t&&!i[t]&&a.push({code:`REFERENCE_MISSING`,message:`Asset "${t}" is not present in ${m}.`,assetId:t,fix:`Run: coreframe assets add <file> --id ${t} --alt "..."`}),r&&a.length===0&&s.length>0&&await E(e,i),{ok:a.length===0,assets:s,fetched:o,problems:a}}async function b({cwd:e=process.cwd(),fix:t=!1}={}){if(t){let t=await y({cwd:e}),n=await b({cwd:e,fix:!1});return{...n,ok:n.ok&&t.ok,problems:[...n.problems,...t.problems]}}let n=await T(e),r=[...n.problems],i=[],a=await I(e);for(let[a,o]of Object.entries(n.manifest)){h.test(a)||r.push({code:`INVALID_ASSET_ID`,message:`Asset ID "${a}" must use lowercase path segments.`,assetId:a}),o.alt.trim()||r.push({code:`INVALID_ALT`,message:`Asset "${a}" is missing alt text.`,assetId:a,file:o.source,fix:`Run: coreframe assets add ${o.source} --id ${a} --alt "..."`}),o.source.startsWith(`${p}/`)||r.push({code:`INVALID_SOURCE_PATH`,message:`Asset "${a}" source must be under ${p}/.`,assetId:a,file:o.source});let n=await R(u(e,o.source)),s=n?await P(e,o.source):!1;n?s||r.push({code:`LFS_NOT_TRACKED`,message:`Source asset "${o.source}" is not tracked by Git LFS.`,assetId:a,file:o.source,fix:`Run: git lfs track "${o.source}" && git add .gitattributes ${o.source}`}):r.push(z(a,o.source));let c=await Promise.all(o.variants.map(async t=>({...t,exists:await R(u(e,t.path))})));(o.variants.length===0||c.some(e=>!e.exists))&&r.push({code:`GENERATED_VARIANT_MISSING`,message:`Asset "${a}" is missing generated variants.`,assetId:a,file:o.source,fix:t?void 0:`Run: coreframe assets build --id ${a}`}),i.push({assetId:a,source:o.source,sourceExists:n,lfsTracked:s,variants:c})}for(let e of a)n.manifest[e.assetId]||r.push({code:`INVALID_REFERENCE`,message:`Asset reference "${e.assetId}" is not present in ${m}.`,assetId:e.assetId,file:e.file,fix:`Run: coreframe assets add <file> --id ${e.assetId} --alt "..."`});return{ok:r.length===0,assets:i,problems:r}}async function x({cwd:e=process.cwd(),env:r=process.env,outputDir:i}={}){let s=[...(await b({cwd:e})).problems],l=[],d=[],f=u(e,i??r.COREFRAME_ASSETS_PUBLISH_DIR??`release-upload/assets`),p=c(f,`asset-publish-report.json`);if(s.length===0){let{manifest:r}=await T(e);for(let[i,a]of Object.entries(r))for(let r of a.variants){let a=u(e,r.path),s=c(f,r.path),p={assetId:i,source:r.path,target:s,size:r.size};if(await R(s)){d.push(p);continue}await n(o(s),{recursive:!0}),await t(a,s),l.push(p)}}let m={ok:s.length===0,uploaded:l,skipped:d,reportPath:p,problems:s};return await n(o(p),{recursive:!0}),await a(p,`${JSON.stringify(m,null,2)}\n`),m}async function S(e,t={}){return y({...t,id:e})}function C(e,t=!1){if(t){console.log(JSON.stringify(e,null,2));return}let n=e;n.problems&&n.problems.length>0&&console.error(B(n.problems)),console.log(n.ok===!1?`Asset workflow has problems.`:`Asset workflow complete.`)}function w(e){if(!h.test(e))throw Error(`Asset ID "${e}" must use lowercase path segments.`)}async function T(e=process.cwd()){let t=u(e,m);if(!await R(t))return{manifest:{},problems:[{code:`MANIFEST_MISSING`,message:`${m} does not exist.`,file:m,fix:`Run: coreframe assets add <file> --id <asset-id> --alt "..."`}]};try{return{manifest:JSON.parse(await r(t,`utf8`)),problems:[]}}catch(e){return{manifest:{},problems:[{code:`INVALID_MANIFEST`,message:`${m} is not valid JSON: ${e.message}`,file:m}]}}}async function E(e,t){let r=u(e,m);await n(o(r),{recursive:!0}),await a(r,`${JSON.stringify(D(t),null,2)}\n`)}function D(e){return Object.fromEntries(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)))}function O(e,t){return c(p,`${e}${s(t).toLowerCase()}`).split(d).join(`/`)}async function k(t,r,i){let s=await j(),l=u(t,i.source),d=Math.min(i.width,1200),f=c(`.coreframe/assets`,r),p=await s(l).resize({width:d,withoutEnlargement:!0}).webp().toBuffer(),m=e(`sha256`).update(p).digest(`hex`).slice(0,12),h=`${f}.${m}.${d}.webp`,g=u(t,h);await n(o(g),{recursive:!0}),await a(g,p);let _=await s(p).metadata();return{format:`webp`,width:_.width??d,height:_.height??Math.round(i.height/i.width*d),path:h,size:p.byteLength,hash:m}}async function A(e){let t=await(await j())(e).metadata();if(!t.width||!t.height)throw Error(`Could not read dimensions for ${e}.`);return{width:t.width,height:t.height}}async function j(){try{return(await import(`sharp`)).default}catch{throw Error(`The assets workflow requires the optional sharp dependency.`)}}async function M(e,t){await f(`git`,[`lfs`,`track`,t],{cwd:e})}async function N(e,t){await f(`git`,[`lfs`,`pull`,`--include=${t}`],{cwd:e})}async function P(e,t){try{return(await f(`git`,[`check-attr`,`filter`,`--`,t],{cwd:e})).stdout.includes(`filter: lfs`)}catch{return!1}}async function F(e){try{let t=await r(e,`utf8`);return _.test(t)}catch{return!1}}async function I(e){let t=await L(e),n=[];for(let i of t){let t=await r(u(e,i),`utf8`);for(let e of t.matchAll(g))n.push({assetId:e[1],file:i})}return n}async function L(e){return(await f(`git`,[`ls-files`,`*.md`,`*.mdx`,`*.ts`,`*.tsx`],{cwd:e})).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).filter(e=>!e.startsWith(`dist/`))}async function R(e){try{return await i(e),!0}catch{return!1}}function z(e,t){return{code:`SOURCE_MISSING`,message:`Source asset "${t}" does not exist.`,assetId:e,file:t,fix:`Run: coreframe assets add <file> --id ${e} --alt "..."`}}function B(e){return e.map(e=>[`${e.code}: ${e.message}`,e.file?` file: ${l(process.cwd(),u(e.file))}`:void 0,e.fix?` fix: ${e.fix}`:void 0].filter(Boolean).join(`
3
2
  `)).join(`
4
- `)}export{v as addAsset,y as buildAssets,b as checkAssets,C as coreframeAssetsPlugin,S as materializeAsset,w as printAssetResult,x as publishAssets};
3
+ `)}export{v as addAsset,y as buildAssets,b as checkAssets,B as formatAssetProblems,S as materializeAsset,C as printAssetResult,x as publishAssets,T as readAssetManifest};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreframe/scripts",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/airlock-labs/coreframe.git",
@@ -1,18 +0,0 @@
1
- import { ConfigEnv, FSWatcher } from "vite";
2
-
3
- //#region image-generator.d.ts
4
- declare function imageGenerator(): {
5
- name: string;
6
- configResolved(config: {
7
- command: ConfigEnv["command"];
8
- }): void;
9
- configureServer(server: {
10
- watcher: FSWatcher;
11
- }): Promise<void>;
12
- applyToEnvironment(environment: {
13
- name: string;
14
- }): boolean;
15
- buildStart(): Promise<void>;
16
- };
17
- //#endregion
18
- export { imageGenerator };
@@ -1 +0,0 @@
1
- import e from"node:path";import t from"node:fs";import{glob as n}from"tinyglobby";function r(){let e;return{name:`image-generator`,configResolved(t){e=t.command},async configureServer(e){await i(),e.watcher.on(`add`,e=>{a(e)&&o(e)}),e.watcher.on(`change`,e=>{a(e)&&o(e,{overwrite:!0})})},applyToEnvironment(e){return e.name===`client`},async buildStart(){e===`build`&&await i()}}}async function i(){let e=await n([`src/**/*@3x.{png,webp}`,`public/**/*@3x.{png,webp}`]);console.log(`[image-generator] Found ${e.length} @3x images.`),await Promise.all(e.map(e=>o(e)))}function a(e){return/@3x\.(png|webp)$/.test(e)}async function o(n,r={}){let i=e.dirname(n),a=e.extname(n),o=e.basename(n,`@3x${a}`),c=[{outputPath:e.join(i,`${o}@2x${a}`),scale:2/3},{outputPath:e.join(i,`${o}@1x${a}`),scale:1/3}].filter(e=>r.overwrite||!t.existsSync(e.outputPath));if(c.length===0)return;let{default:l}=await import(`sharp`),u;try{u=(await l(n).metadata()).width}catch(e){console.error(`[image-generator] Failed to read metadata for ${n}`,e);return}if(!u){console.error(`[image-generator] Skipping ${n}; image width could not be read.`);return}await Promise.all(c.map(e=>s({file:n,outputPath:e.outputPath,sharp:l,width:Math.round(u*e.scale)})))}async function s(e){try{console.log(`[image-generator] Generating ${e.outputPath} (${e.width}w)`),await e.sharp(e.file).resize({width:e.width}).toFile(e.outputPath)}catch(t){console.error(`[image-generator] Failed to process ${e.file} for ${e.outputPath}`,t)}}export{r as imageGenerator};