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)
- 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.
- The babel import check throws
disallowed_import for any package not in the hardcoded allowedPackages list (url, crypto, nango, zod, …), except import type.
- 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:
- Skip the
disallowed_import throw in the import validator.
- 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.
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 aworkspace:*dependency):The goal:
sync-contacts.tsshould be able toimport { 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)external-npm-packagesesbuild plugin marks every non-relative specifier (/^[^./\s]/) asexternal, so@repo/sharedis never bundled and fails in the cloud sandbox.disallowed_importfor any package not in the hardcodedallowedPackageslist (url,crypto,nango,zod, …), exceptimport type.../../packages/shared/...) do get bundled by esbuild, but thenode16typecheck (hardcodedtsconfig, not user-editable) rejects them when the source package uses a differentmoduleResolution(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
.cjswhere 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 compilewould:disallowed_importthrow in the import validator.externalin theonResolvehook — let esbuild resolve them normally via node resolution (the workspace symlink → the package'sexports/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 undernode16, 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
bundleDependenciesbehavior in the zero-yaml compiler. Happy to align on the config shape/naming first.