/** * Shared connector compile pipeline. * * Three packages (`@lobu/connector-worker` itself, `@lobu/cli`, and * `@lobu/server`) each used to ship their own near-identical copies of: * * - `findBundledConnectorFile(key)` — walks a list of candidate dirs * trying both filename conventions (`browser.evaluate → browser/evaluate.ts` * and `chrome.tabs → chrome_tabs.ts`). * - a connector compile step — esbuild bundle with the `npm:` specifier * plugin, the `lobu` / `@lobu/connector-sdk` aliases, and an mtime-keyed * LRU cache. * - The `npm:` specifier resolver plugin. * - The `EXTERNAL_RUNTIME_DEPS` constant. * * Three copies meant three "keep these in sync" comments and three places * to fix every esbuild-flag or candidate-dir change. This module is the * one place that owns those mechanics; each caller supplies its own * candidate-dir list (and optional warn hook) since those are genuinely * environment-specific (gateway pod vs worker pod vs npm-installed CLI). */ import { type Plugin } from 'esbuild'; export { assertExternalDepsResolvable, COMPILE_CONFIG_HASH, computeCompileConfigHash, EXTERNAL_RUNTIME_DEPS, RUNTIME_PROVIDED_PACKAGES, } from '../runtime-deps.js'; /** * Resolve a connector_key to a `.ts` source file under one of the supplied * candidate directories. * * Tries two filename conventions in order: * - subdirectory layout: `browser.evaluate` → `browser/evaluate.ts` * (lets us group related primitives without renaming the key); * - flat-with-underscores: `chrome.tabs` → `chrome_tabs.ts` * (existing convention). * * Returns the absolute path of the first match, or `null` if none exists. * Performs no caching of its own — callers that hit this on a hot path * (gateway worker-poll, CLI compile loop) can layer their own memo on * top, since the right TTL depends on whether they expect new connector * files to appear at runtime. */ export declare function findBundledConnectorFile(key: string, candidateDirs: readonly string[]): string | null; /** * Matches the connector SDK as a root or subpath import, under either the * `lobu` alias or its real package name. Shared with the server's source-text * compiler (`packages/server/src/utils/compiler-core.ts`) so the two compilers * cannot disagree about what counts as an SDK import — one externalizes it, * the other resolves it to a file, and a specifier only one of them recognises * would compile in one runtime and fail in the other. */ export declare const SDK_SPECIFIER_RE: RegExp; /** Normalize the `lobu` alias to the real package name, preserving any subpath. */ export declare function normalizeSdkSpecifier(specifier: string): string; /** * esbuild options for code that runs inside a V8 isolate: the gateway's script * sandbox (`packages/server/src/sandbox/run-script.ts`, via the server's * `compiler-core`) and the connector isolate lane. `external: []` inlines every * import because an isolate has no module resolver, and `platform: 'node'` * leaves Node builtins as bare `require()` calls that throw at load — the * fail-closed signal `findIsolateIneligibleBuiltins` and the lane tests key * on. One constant so the runtime and the tests that classify bundles can * never disagree. */ export declare const ISOLATE_LANE_BUILD_OPTIONS: { readonly format: "cjs"; readonly target: "esnext"; readonly platform: "node"; readonly conditions: ["workerd"]; readonly supported: { readonly 'dynamic-import': false; }; readonly external: []; }; export interface NpmSpecifierPluginOptions { /** * Called when a `npm:foo@1.2.3` import resolves to a package that's not * installed in the current environment. The plugin externalises the * import (so the bundle still emits) and the runtime must supply it. * Use this hook to log / surface the externalisation. * Ignored under `unresolved: 'error'`. */ onUnresolved?: (info: { bareSpecifier: string; importer: string; }) => void; /** * What to do when the bare package can't be resolved in the build * environment: `'externalize'` (default) emits the import as external and * the runtime must provide it; `'error'` fails the build with esbuild's * resolution error (used by compilers whose artifacts must be fully * self-contained, e.g. the server's source-text compiler). */ unresolved?: 'externalize' | 'error'; } /** * esbuild plugin that strips the `npm:` prefix from connector imports * (`import x from 'npm:foo@1.2.3'`) and resolves the bare specifier * against node_modules. Unresolved packages are externalised or failed * per {@link NpmSpecifierPluginOptions.unresolved}. Registered as an * onResolve hook, so it only ever sees real module declarations parsed * from the source AST — `npm:` text inside strings or comments is data, * never rewritten (#2043). */ export declare function createNpmSpecifierPlugin(options?: NpmSpecifierPluginOptions): Plugin; /** * Flatten a multi-file connector source into ONE self-contained source text: * the relative import graph is inlined (source-level bundle) while `lobu` / * `@lobu/connector-sdk`, `npm:` specifiers, bare packages, and node builtins * stay as import statements for the downstream compiler to resolve. * * This is what install paths persist as `source_code` for file-backed * connectors: a stored source must recompile under the strict single-file * source-text compiler (`compileConnectorSource`) years later, on any replica, * with no repo checkout — raw multi-file text with relative imports can never * do that (#2042, the Gmail scraper-utils outage). * * Deterministic: same inputs produce the same output (esbuild text transform, * no minification, no timestamps). */ export declare function flattenConnectorSourceFromFile(filePath: string): Promise; interface IsolateCompileOptions { /** * Max entries kept in the mtime-keyed LRU. Each entry is a self-contained * bundle — the connector's own code plus the SDK and every npm dep inlined, * since the isolate has no module loader to resolve anything at run time. * Cap default 8 keeps memory bounded; pass a smaller value in * memory-constrained environments. * @default 8 */ cacheMax?: number; } export interface IsolateBundle { /** CJS bundle text; `module.exports.default` is the ConnectorRuntime class. */ code: string; /** Node builtins the bundle still requires (`node:` prefix stripped), sorted. Empty means isolate-eligible. */ builtins: string[]; } /** * Compile a connector source file into a self-contained CJS bundle for the * isolate lane (`ISOLATE_LANE_BUILD_OPTIONS`): the SDK and every pure-JS * dependency are inlined; `npm:` specifiers must resolve (`unresolved: * 'error'`) because the isolate cannot supply them at runtime. The metafile * reports which Node builtins survive as bare requires, which is how a bundle * is found to be unloadable before it ever reaches an isolate. */ export declare function createIsolateConnectorCompiler(options?: IsolateCompileOptions): { bundleConnectorForIsolate: (filePath: string) => Promise; compileConnectorForIsolateFromFile: (filePath: string) => Promise; compileConnectorForIsolateFromSource: (sourceCode: string) => Promise; }; //# sourceMappingURL=index.d.ts.map