Skip to content
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
10 changes: 1 addition & 9 deletions apps/sim/lib/content/registry-factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,7 @@ import os from 'os'
import path from 'path'
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'

/**
* `sharp` resolves a platform-specific `@img/sharp-*` native binary that the
* standalone file tracer cannot follow, so a deployment can ship without it. It
* must therefore be loaded lazily and its failure contained: an unreadable OG
* dimension is optional metadata, not a reason to take down `/blog`, `/library`,
* and every tag, author, slug, and RSS route that reads the registry.
*
* This mock makes `import('sharp')` fail the way a missing native binary does.
*/
/** Fails `import('sharp')` the way an unloadable native binary does. */
vi.mock('sharp', () => {
throw new Error('Could not load the sharp module using the linux-x64 runtime')
})
Expand Down
9 changes: 3 additions & 6 deletions apps/sim/lib/content/registry-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,9 @@ export function createContentRegistry(config: ContentRegistryConfig): ContentReg
* `image-size` package, archived upstream with unpatched DoS advisories in
* its ICNS/JXL/HEIF parsers (GHSA-w3rx-r6r6-pgpr, GHSA-5p2g-fcmc-qvqq).
*
* `sharp` is loaded lazily, never as a top-level import. It resolves a
* platform-specific `@img/sharp-*` native binary that the standalone file
* tracer cannot follow, so a deployment that ships without it makes
* `import 'sharp'` throw at module scope — which would take down every route
* that touches this registry (`/blog`, `/library`, their tag, author, slug,
* and RSS routes) rather than degrading one optional OG dimension.
* Imported lazily, never at module scope: sharp resolves a native binary, and a
* top-level import that fails to load would take down every route reading this
* registry instead of dropping one optional dimension.
*/
async function readOgImageDimensions(
ogImage: string
Expand Down
10 changes: 5 additions & 5 deletions apps/sim/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ const nextConfig: NextConfig = {
'/api/internal/file-doc/seed': ['./node_modules/jsdom/**/*'],
'/api/internal/file-doc/merge': ['./node_modules/jsdom/**/*'],
'/api/internal/file-doc/persist': ['./node_modules/jsdom/**/*'],
'/*': [
'./node_modules/sharp/**/*',
'./node_modules/@img/**/*',
'./lib/execution/sandbox/bundles/*.cjs',
],
/**
* No `sharp`/`@img` entries: these globs resolve against apps/sim while both hoist to the
* monorepo root, so they matched nothing. docker/app.Dockerfile copies them instead.
*/
'/*': ['./lib/execution/sandbox/bundles/*.cjs'],
},
experimental: {
/**
Expand Down
9 changes: 9 additions & 0 deletions docker/app.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ COPY --from=deps --chown=nextjs:nodejs /app/node_modules/lib0 ./node_modules/lib
COPY --from=deps --chown=nextjs:nodejs /app/node_modules/yjs ./node_modules/yjs
COPY --from=deps --chown=nextjs:nodejs /app/node_modules/y-protocols ./node_modules/y-protocols

# `@img/sharp-<platform>` loads libvips from `@img/sharp-libvips-<platform>` through the dynamic
# linker, not a JS require, so the tracer copies the binding but not the library and sharp dies with
# "ERR_DLOPEN_FAILED: libvips-cpp.so: cannot open shared object file". Same hoisting reason as the Yjs
# stack above. Copying whole directories keeps these arch-agnostic (each build's deps stage holds only
# its own platform's packages) and keeps sharp and its binding on the same install. Must stay below
# the standalone COPY, which ships its own partial node_modules that would otherwise win.
COPY --from=deps --chown=nextjs:nodejs /app/node_modules/sharp ./node_modules/sharp
COPY --from=deps --chown=nextjs:nodejs /app/node_modules/@img ./node_modules/@img

# Copy the isolated-vm worker script
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/execution/isolated-vm-worker.cjs ./apps/sim/lib/execution/isolated-vm-worker.cjs

Expand Down
Loading