Skip to content

Support bundling workspace/internal dependencies in zero-yaml compile (monorepo) #6425

Description

@diegoleme

Summary

In a monorepo, a sync function often needs to import shared logic from an internal workspace package — normalization helpers, shared types, validation, etc. Today nango compile (zero-yaml) makes this impossible: the helper has to be manually copy-pasted into the integrations folder and kept in sync by hand, which silently drifts from the source of truth.

Context

A typical pnpm + Turborepo layout, where a sync wants to reuse a shared internal package (@repo/shared, declared as a workspace:* dependency):

monorepo/
├── pnpm-workspace.yaml
├── packages/
│   └── shared/                      # @repo/shared — shared helpers & types
│       ├── package.json             #   exports "." -> dist/index.js, types dist/index.d.ts
│       └── src/index.ts
└── apps/
    └── nango/                       # Nango integrations folder
        ├── index.ts
        └── my-integration/
            └── syncs/
                └── sync-contacts.ts  # wants: import { normalize } from "@repo/shared"

The goal: sync-contacts.ts should be able to import { normalize } from "@repo/shared" so the data ingested from the provider is processed with the exact same logic used elsewhere in the codebase — instead of a hand-maintained copy.

What blocks it today (zero-yaml compile.js)

  1. The external-npm-packages esbuild plugin marks every non-relative specifier (/^[^./\s]/) as external, so @repo/shared is never bundled and fails in the cloud sandbox.
  2. The babel import check throws disallowed_import for any package not in the hardcoded allowedPackages list (url, crypto, nango, zod, …), except import type.
  3. Relative imports that reach outside the project (../../packages/shared/...) do get bundled by esbuild, but the node16 typecheck (hardcoded tsconfig, not user-editable) rejects them when the source package uses a different moduleResolution (e.g. .ts-extension imports → TS5097).

Net effect: there is no first-class way to share code from a workspace package, even though the deployed artifact is a single bundled .cjs where the dependency could simply be inlined.

Proposed fix

Add an opt-in config (e.g. a bundleDependencies: string[] field) listing internal packages that should be bundled instead of externalized. For packages in that list, nango compile would:

  1. Skip the disallowed_import throw in the import validator.
  2. Not mark them external in the onResolve hook — let esbuild resolve them normally via node resolution (the workspace symlink → the package's exports/dist), so the code is inlined into the .cjs.

Type-checking already works for this case as long as the package exposes types via its exports/types (resolved under node16, e.g. dist/index.d.ts).

Why this is safe for the sandbox: because the dependency is inlined into the bundle, the cloud runtime does not need it installed — this doesn't weaken the isolation model; it's purely a build-time resolution change, gated behind explicit opt-in.

Question

Does this direction sound acceptable to you? If so, I'd be happy to open a PR implementing the opt-in bundleDependencies behavior in the zero-yaml compiler. Happy to align on the config shape/naming first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions