diff --git a/.changeset/fix-mirror-state-dynamic-provider.md b/.changeset/fix-mirror-state-dynamic-provider.md new file mode 100644 index 0000000..8e51e6b --- /dev/null +++ b/.changeset/fix-mirror-state-dynamic-provider.md @@ -0,0 +1,5 @@ +--- +'@opsen/docker-compose': patch +--- + +Fix MirrorStateProvider dynamic provider module resolution to survive Pulumi closure serialization diff --git a/packages/docker-compose/src/mirror-state/mirror-state.ts b/packages/docker-compose/src/mirror-state/mirror-state.ts index 35663d7..0009222 100644 --- a/packages/docker-compose/src/mirror-state/mirror-state.ts +++ b/packages/docker-compose/src/mirror-state/mirror-state.ts @@ -1,15 +1,24 @@ import { dynamic, type CustomResourceOptions } from '@pulumi/pulumi' import type { MirrorStateProviderInputs, MirrorStateInputs } from './types' -// Imported dynamically inside provider methods to avoid capturing module -// references in Pulumi's closure serialization (breaks with pnpm store paths). type ServerModule = typeof import('./server') type CommonModule = typeof import('./common') +// Resolve absolute paths at module load time so they survive Pulumi's closure +// serialization. The dynamic provider runs plain Node.js (no tsx), so paths must +// point to compiled .js files in dist/. When loaded via tsx from src/, remap accordingly. +function resolveForDynamicProvider(relativePath: string): string { + let resolved = require.resolve(relativePath) + resolved = resolved.replace(/\.ts$/, '.js').replace(/\/src\//, '/dist/') + return resolved +} +const serverPath = resolveForDynamicProvider('./server') +const commonPath = resolveForDynamicProvider('./common') + export class MirrorStateProvider implements dynamic.ResourceProvider { async create(inputs: MirrorStateProviderInputs): Promise { // eslint-disable-next-line @typescript-eslint/no-require-imports - const server: ServerModule = require('./server') + const server: ServerModule = require(serverPath) const hash = await server.sendData(inputs) return { id: `${inputs.connection.user}: ${inputs.remotePath}`, @@ -23,7 +32,7 @@ export class MirrorStateProvider implements dynamic.ResourceProvider { news: MirrorStateProviderInputs, ): Promise { // eslint-disable-next-line @typescript-eslint/no-require-imports - const server: ServerModule = require('./server') + const server: ServerModule = require(serverPath) const hash = await server.sendData(news) return { outs: { ...news, filesHash: hash } } } @@ -34,9 +43,9 @@ export class MirrorStateProvider implements dynamic.ResourceProvider { news: MirrorStateProviderInputs, ): Promise { // eslint-disable-next-line @typescript-eslint/no-require-imports - const server: ServerModule = require('./server') + const server: ServerModule = require(serverPath) // eslint-disable-next-line @typescript-eslint/no-require-imports - const common: CommonModule = require('./common') + const common: CommonModule = require(commonPath) try { const remoteState = await server.getData(news) return { @@ -55,7 +64,7 @@ export class MirrorStateProvider implements dynamic.ResourceProvider { async delete(_id: string, props: MirrorStateProviderInputs): Promise { // eslint-disable-next-line @typescript-eslint/no-require-imports - const server: ServerModule = require('./server') + const server: ServerModule = require(serverPath) await server.removeData(props) } }