@neon/config 1.0.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { ConfigLoadError, isPlatformError } from "./errors.js";
1
+ import { ConfigLoadError, ErrorCode, isPlatformError } from "./errors.js";
2
2
  import { defineConfig } from "./define-config.js";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  import { homedir } from "node:os";
@@ -32,6 +32,25 @@ const DEFAULT_CONFIG_FILENAMES = [
32
32
  * never pay the import cost.
33
33
  */
34
34
  async function loadConfigFromFile(options = {}) {
35
+ return await withSerializedConfigLoad(() => loadConfigFromFileUnlocked(options));
36
+ }
37
+ async function loadConfigFromFileUnlocked(options) {
38
+ if (options.unsetFunctionEnv !== "omit") return await loadConfigOnce(options);
39
+ try {
40
+ return await loadConfigOnce(options);
41
+ } catch (err) {
42
+ const keys = unsetFunctionEnvKeys(err);
43
+ if (keys === null) throw err;
44
+ return await withPlaceholderFunctionEnv(async () => {
45
+ const loaded = await loadConfigOnce(options);
46
+ return {
47
+ ...loaded,
48
+ config: withoutFunctionEnvKeys(loaded.config, new Set(keys))
49
+ };
50
+ });
51
+ }
52
+ }
53
+ async function loadConfigOnce(options) {
35
54
  const resolvedPath = options.path ? resolveExplicitPath(options.path, options.cwd) : findDefaultConfig(options.cwd, options.stopAt);
36
55
  if (!resolvedPath) throw new ConfigLoadError([
37
56
  `Could not find a Neon config file while walking up from ${resolve(options.cwd ?? process.cwd())}.`,
@@ -40,7 +59,7 @@ async function loadConfigFromFile(options = {}) {
40
59
  ].join("\n"));
41
60
  let mod;
42
61
  try {
43
- mod = await importModule(resolvedPath);
62
+ mod = await importModule(resolvedPath, options.unsetFunctionEnv === "omit");
44
63
  } catch (cause) {
45
64
  if (isPlatformError(cause)) throw cause;
46
65
  throw new ConfigLoadError([
@@ -80,9 +99,9 @@ function findDefaultConfig(cwd, stopAt) {
80
99
  current = parent;
81
100
  }
82
101
  }
83
- async function importModule(absPath) {
102
+ async function importModule(absPath, forceJiti = false) {
84
103
  const lower = absPath.toLowerCase();
85
- if (!(lower.endsWith(".ts") || lower.endsWith(".mts") || lower.endsWith(".cts"))) return import(pathToFileURL(absPath).href);
104
+ if (!(forceJiti || lower.endsWith(".ts") || lower.endsWith(".mts") || lower.endsWith(".cts"))) return import(pathToFileURL(absPath).href);
86
105
  const createJiti = extractCreateJiti(await import("jiti"));
87
106
  if (!createJiti) throw new ConfigLoadError(["jiti is required to load TypeScript config files but could not be initialised.", "Reinstall the package dependencies (`pnpm install` / `npm install`) — jiti is a runtime dependency of @neon/config."].join(" "));
88
107
  return createJiti(pathToFileURL(absPath).href, {
@@ -114,6 +133,75 @@ function safeIsFile(path) {
114
133
  return false;
115
134
  }
116
135
  }
136
+ const UNSET_FUNCTION_ENV_ISSUE = /^preview\.functions\.[^.]+\.env\.(.+): Environment variable "\1" for function ".+" is undefined/;
137
+ function unsetFunctionEnvKeys(err) {
138
+ if (!isPlatformError(err) || err.code !== ErrorCode.InvalidConfig) return null;
139
+ const issues = platformErrorIssues(err);
140
+ if (issues === null || issues.length === 0) return null;
141
+ const keys = [];
142
+ for (const issue of issues) {
143
+ const key = UNSET_FUNCTION_ENV_ISSUE.exec(issue)?.[1];
144
+ if (key === void 0) return null;
145
+ keys.push(key);
146
+ }
147
+ return keys;
148
+ }
149
+ function platformErrorIssues(err) {
150
+ if (typeof err !== "object" || err === null || !("issues" in err)) return null;
151
+ const { issues } = err;
152
+ if (!Array.isArray(issues) || issues.some((issue) => typeof issue !== "string")) return null;
153
+ return issues;
154
+ }
155
+ async function withPlaceholderFunctionEnv(run) {
156
+ const original = process.env;
157
+ const proxy = new Proxy(original, { get(target, prop, receiver) {
158
+ if (typeof prop === "symbol") return Reflect.get(target, prop, receiver);
159
+ const value = Reflect.get(target, prop, receiver);
160
+ return value === void 0 ? "" : value;
161
+ } });
162
+ process.env = proxy;
163
+ try {
164
+ return await run();
165
+ } finally {
166
+ process.env = original;
167
+ }
168
+ }
169
+ const CONFIG_LOAD_LOCK = Symbol.for("@neon/config loadConfigFromFile lock");
170
+ function configLoadLock() {
171
+ const g = globalThis;
172
+ const lock = g[CONFIG_LOAD_LOCK] ?? { chain: Promise.resolve() };
173
+ g[CONFIG_LOAD_LOCK] = lock;
174
+ return lock;
175
+ }
176
+ async function withSerializedConfigLoad(run) {
177
+ const lock = configLoadLock();
178
+ const next = lock.chain.then(run, run);
179
+ lock.chain = next.then(() => void 0, () => void 0);
180
+ return next;
181
+ }
182
+ function withoutFunctionEnvKeys(config, keys) {
183
+ const functions = config.preview?.functions;
184
+ if (!functions) return config;
185
+ const nextFunctions = {};
186
+ for (const [slug, fn] of Object.entries(functions)) {
187
+ if (!fn.env) {
188
+ nextFunctions[slug] = fn;
189
+ continue;
190
+ }
191
+ const env = Object.fromEntries(Object.entries(fn.env).filter(([key]) => !keys.has(key)));
192
+ nextFunctions[slug] = {
193
+ ...fn,
194
+ env
195
+ };
196
+ }
197
+ return Object.freeze({
198
+ ...config,
199
+ preview: {
200
+ ...config.preview,
201
+ functions: nextFunctions
202
+ }
203
+ });
204
+ }
117
205
  //#endregion
118
206
  export { DEFAULT_CONFIG_FILENAMES, loadConfigFromFile };
119
207
 
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","names":[],"sources":["../../src/lib/loader.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { defineConfig } from \"./define-config.js\";\nimport { ConfigLoadError, isPlatformError } from \"./errors.js\";\nimport type { Config } from \"./types.js\";\n\n/**\n * Default file names tried (in order) when {@link loadConfigFromFile} is called without an\n * explicit path. We accept `.ts` first because that's the documented format; `.mjs` and `.js`\n * fall out for free since jiti handles all of them.\n */\nexport const DEFAULT_CONFIG_FILENAMES = [\n\t\"neon.ts\",\n\t\"neon.mts\",\n\t\"neon.js\",\n\t\"neon.mjs\",\n] as const;\n\nexport interface LoadConfigOptions {\n\t/** Explicit absolute or cwd-relative path to a config file. Takes precedence over the search. */\n\tpath?: string;\n\t/** Starting directory for the upward search. Defaults to `process.cwd()`. */\n\tcwd?: string;\n\t/**\n\t * Hard ceiling for the upward walk — once `current === stopAt` the search returns\n\t * `null` even if no `.git` boundary was hit. Defaults to the OS home directory so\n\t * stray runs from outside any repo never leak into the user's `~` files.\n\t */\n\tstopAt?: string;\n}\n\n/**\n * Load a `neon.ts` (or any other supported extension) and return the validated {@link Config}.\n *\n * Behavior:\n * - When `path` is set, that file is loaded directly. The file must exist and must default-export\n * a value produced by `defineConfig()`.\n * - When `path` is omitted, we walk up from `cwd` picking the **closest** file matching\n * {@link DEFAULT_CONFIG_FILENAMES}. The walk is monorepo-friendly: intermediate\n * `package.json` files do **not** stop it, so a single `neon.ts` lifted to the workspace\n * root keeps working when invoked from inside any sub-package. The walk terminates at the\n * first directory containing `.git`, at `stopAt`, or at the filesystem root.\n *\n * jiti is loaded lazily so that callers who pass an already-resolved `Config` to `pushConfig`\n * never pay the import cost.\n */\nexport async function loadConfigFromFile(\n\toptions: LoadConfigOptions = {},\n): Promise<{\n\tconfig: Config;\n\tresolvedPath: string;\n}> {\n\tconst resolvedPath = options.path\n\t\t? resolveExplicitPath(options.path, options.cwd)\n\t\t: findDefaultConfig(options.cwd, options.stopAt);\n\n\tif (!resolvedPath) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`Could not find a Neon config file while walking up from ${resolve(options.cwd ?? process.cwd())}.`,\n\t\t\t\t`Looked for: ${DEFAULT_CONFIG_FILENAMES.join(\", \")} (stopping at the first directory with a \\`.git\\`).`,\n\t\t\t\t`Create one at your repository root (or anywhere on the path from cwd up to .git), or pass an explicit \\`configPath\\` (SDK) / \\`--config <path>\\` (CLI).`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\tlet mod: unknown;\n\ttry {\n\t\tmod = await importModule(resolvedPath);\n\t} catch (cause) {\n\t\t// `defineConfig()` runs at module-eval time, so a config the user got *wrong*\n\t\t// (a bad function slug, an unknown key, an invalid duration, …) throws a\n\t\t// PlatformError from inside this import. That error already pinpoints the exact\n\t\t// field and reason, so surface it verbatim — burying it under the generic\n\t\t// \"this is usually a TypeScript syntax error\" hint sent users hunting for a\n\t\t// syntax bug that isn't there. The hint is reserved for genuine evaluation\n\t\t// failures (syntax errors, missing deps, thrown runtime exceptions).\n\t\tif (isPlatformError(cause)) {\n\t\t\tthrow cause;\n\t\t}\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`Failed to evaluate ${resolvedPath}.`,\n\t\t\t\t`Underlying error: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\t\"This is usually a TypeScript syntax error, a missing dependency, or a runtime exception inside the config file. Run the file directly (e.g. `npx tsx neon.ts`) to reproduce.\",\n\t\t\t].join(\"\\n\"),\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tconst exported = extractDefaultExport(mod);\n\tif (exported === undefined) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`${resolvedPath} loaded successfully but did not default-export a config.`,\n\t\t\t\t\"Add `export default defineConfig({ ... })` at the bottom of the file. (Named exports are ignored.)\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\t// Run through defineConfig to validate any function the user might have constructed manually.\n\tconst config = defineConfig(exported as Config);\n\treturn { config, resolvedPath };\n}\n\nfunction resolveExplicitPath(input: string, cwd?: string): string {\n\tconst base = resolve(cwd ?? process.cwd());\n\tconst abs = isAbsolute(input) ? input : resolve(base, input);\n\tif (!existsSync(abs)) {\n\t\tthrow new ConfigLoadError(\n\t\t\t`Config file not found at ${abs}. The path was resolved from \\`${input}\\` against ${base}.`,\n\t\t);\n\t}\n\tconst s = statSync(abs);\n\tif (!s.isFile()) {\n\t\tthrow new ConfigLoadError(\n\t\t\t`Config path ${abs} is a directory, not a file. Pass a path to the file itself (e.g. ./neon.ts).`,\n\t\t);\n\t}\n\treturn abs;\n}\n\nfunction findDefaultConfig(\n\tcwd: string | undefined,\n\tstopAt: string | undefined,\n): string | null {\n\tlet current = resolve(cwd ?? process.cwd());\n\tconst stop = resolve(stopAt ?? homedir());\n\tlet lastSeen: string | null = null;\n\n\twhile (true) {\n\t\tfor (const name of DEFAULT_CONFIG_FILENAMES) {\n\t\t\tconst candidate = resolve(current, name);\n\t\t\tif (existsSync(candidate) && safeIsFile(candidate))\n\t\t\t\treturn candidate;\n\t\t}\n\n\t\t// `.git` is the canonical repo-root marker. `package.json` is deliberately *not*\n\t\t// a stop: monorepos lift `neon.ts` above sub-package package.jsons.\n\t\tif (existsSync(resolve(current, \".git\"))) return null;\n\t\tif (current === stop) return null;\n\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parent === lastSeen) return null;\n\t\tlastSeen = current;\n\t\tcurrent = parent;\n\t}\n}\n\nasync function importModule(absPath: string): Promise<unknown> {\n\tconst lower = absPath.toLowerCase();\n\tconst needsJiti =\n\t\tlower.endsWith(\".ts\") ||\n\t\tlower.endsWith(\".mts\") ||\n\t\tlower.endsWith(\".cts\");\n\n\tif (!needsJiti) {\n\t\treturn import(pathToFileURL(absPath).href);\n\t}\n\n\tconst jitiModule: unknown = await import(\"jiti\");\n\tconst createJiti = extractCreateJiti(jitiModule);\n\tif (!createJiti) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t\"jiti is required to load TypeScript config files but could not be initialised.\",\n\t\t\t\t\"Reinstall the package dependencies (`pnpm install` / `npm install`) — jiti is a runtime dependency of @neon/config.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\tconst jiti = createJiti(pathToFileURL(absPath).href, {\n\t\tinteropDefault: true,\n\t\tmoduleCache: false,\n\t});\n\treturn jiti.import(absPath);\n}\n\nfunction extractCreateJiti(\n\tmod: unknown,\n): ((id: string, options?: unknown) => JitiInstance) | null {\n\tif (mod === null || typeof mod !== \"object\") return null;\n\tconst obj = mod as Record<string, unknown>;\n\tif (typeof obj.createJiti === \"function\") {\n\t\treturn obj.createJiti as (\n\t\t\tid: string,\n\t\t\toptions?: unknown,\n\t\t) => JitiInstance;\n\t}\n\tconst def = obj.default;\n\tif (def !== null && typeof def === \"object\") {\n\t\tconst defObj = def as Record<string, unknown>;\n\t\tif (typeof defObj.createJiti === \"function\") {\n\t\t\treturn defObj.createJiti as (\n\t\t\t\tid: string,\n\t\t\t\toptions?: unknown,\n\t\t\t) => JitiInstance;\n\t\t}\n\t}\n\treturn null;\n}\n\ninterface JitiInstance {\n\timport(id: string): Promise<unknown>;\n}\n\nfunction extractDefaultExport(mod: unknown): unknown {\n\tif (mod === null || typeof mod !== \"object\") return mod;\n\tconst obj = mod as Record<string, unknown>;\n\tif (\"default\" in obj && obj.default !== undefined) return obj.default;\n\t// No `default` export. If the module itself is a function, treat it as the config —\n\t// that lets tests and advanced users skip the wrapper.\n\t// Otherwise, return `undefined` so the caller surfaces a clear ConfigLoadError.\n\tif (typeof mod === \"function\") return mod;\n\treturn undefined;\n}\n\nfunction safeIsFile(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","names":[],"sources":["../../src/lib/loader.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { defineConfig } from \"./define-config.js\";\nimport { ConfigLoadError, ErrorCode, isPlatformError } from \"./errors.js\";\nimport type { Config, FunctionDef } from \"./types.js\";\n\n/**\n * Default file names tried (in order) when {@link loadConfigFromFile} is called without an\n * explicit path. We accept `.ts` first because that's the documented format; `.mjs` and `.js`\n * fall out for free since jiti handles all of them.\n */\nexport const DEFAULT_CONFIG_FILENAMES = [\n\t\"neon.ts\",\n\t\"neon.mts\",\n\t\"neon.js\",\n\t\"neon.mjs\",\n] as const;\n\nexport interface LoadConfigOptions {\n\t/** Explicit absolute or cwd-relative path to a config file. Takes precedence over the search. */\n\tpath?: string;\n\t/** Starting directory for the upward search. Defaults to `process.cwd()`. */\n\tcwd?: string;\n\t/**\n\t * Hard ceiling for the upward walk — once `current === stopAt` the search returns\n\t * `null` even if no `.git` boundary was hit. Defaults to the OS home directory so\n\t * stray runs from outside any repo never leak into the user's `~` files.\n\t */\n\tstopAt?: string;\n\t/**\n\t * `\"error\"` (default) prevents deploy and dev from proceeding without\n\t * function secrets.\n\t * `\"omit\"` is for metadata-only reads because apply or deploy would lose the\n\t * omitted keys.\n\t */\n\tunsetFunctionEnv?: \"error\" | \"omit\";\n}\n\n/**\n * Load a `neon.ts` (or any other supported extension) and return the validated {@link Config}.\n *\n * Behavior:\n * - When `path` is set, that file is loaded directly. The file must exist and must default-export\n * a value produced by `defineConfig()`.\n * - When `path` is omitted, we walk up from `cwd` picking the **closest** file matching\n * {@link DEFAULT_CONFIG_FILENAMES}. The walk is monorepo-friendly: intermediate\n * `package.json` files do **not** stop it, so a single `neon.ts` lifted to the workspace\n * root keeps working when invoked from inside any sub-package. The walk terminates at the\n * first directory containing `.git`, at `stopAt`, or at the filesystem root.\n *\n * jiti is loaded lazily so that callers who pass an already-resolved `Config` to `pushConfig`\n * never pay the import cost.\n */\nexport async function loadConfigFromFile(\n\toptions: LoadConfigOptions = {},\n): Promise<{\n\tconfig: Config;\n\tresolvedPath: string;\n}> {\n\t// The omit reload replaces process.env, which is process-global, including\n\t// across duplicate @neon/config copies. Queue loads on globalThis.\n\treturn await withSerializedConfigLoad(() =>\n\t\tloadConfigFromFileUnlocked(options),\n\t);\n}\n\nasync function loadConfigFromFileUnlocked(options: LoadConfigOptions): Promise<{\n\tconfig: Config;\n\tresolvedPath: string;\n}> {\n\tif (options.unsetFunctionEnv !== \"omit\") {\n\t\treturn await loadConfigOnce(options);\n\t}\n\n\ttry {\n\t\treturn await loadConfigOnce(options);\n\t} catch (err) {\n\t\tconst keys = unsetFunctionEnvKeys(err);\n\t\tif (keys === null) throw err;\n\t\t// The user's neon.ts may resolve another @neon/config copy, so the reload\n\t\t// input must satisfy its validation.\n\t\treturn await withPlaceholderFunctionEnv(async () => {\n\t\t\tconst loaded = await loadConfigOnce(options);\n\t\t\treturn {\n\t\t\t\t...loaded,\n\t\t\t\tconfig: withoutFunctionEnvKeys(loaded.config, new Set(keys)),\n\t\t\t};\n\t\t});\n\t}\n}\n\nasync function loadConfigOnce(options: LoadConfigOptions): Promise<{\n\tconfig: Config;\n\tresolvedPath: string;\n}> {\n\tconst resolvedPath = options.path\n\t\t? resolveExplicitPath(options.path, options.cwd)\n\t\t: findDefaultConfig(options.cwd, options.stopAt);\n\n\tif (!resolvedPath) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`Could not find a Neon config file while walking up from ${resolve(options.cwd ?? process.cwd())}.`,\n\t\t\t\t`Looked for: ${DEFAULT_CONFIG_FILENAMES.join(\", \")} (stopping at the first directory with a \\`.git\\`).`,\n\t\t\t\t`Create one at your repository root (or anywhere on the path from cwd up to .git), or pass an explicit \\`configPath\\` (SDK) / \\`--config <path>\\` (CLI).`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\tlet mod: unknown;\n\ttry {\n\t\tmod = await importModule(\n\t\t\tresolvedPath,\n\t\t\toptions.unsetFunctionEnv === \"omit\",\n\t\t);\n\t} catch (cause) {\n\t\t// `defineConfig()` runs at module-eval time, so a config the user got *wrong*\n\t\t// (a bad function slug, an unknown key, an invalid duration, …) throws a\n\t\t// PlatformError from inside this import. That error already pinpoints the exact\n\t\t// field and reason, so surface it verbatim — burying it under the generic\n\t\t// \"this is usually a TypeScript syntax error\" hint sent users hunting for a\n\t\t// syntax bug that isn't there. The hint is reserved for genuine evaluation\n\t\t// failures (syntax errors, missing deps, thrown runtime exceptions).\n\t\tif (isPlatformError(cause)) {\n\t\t\tthrow cause;\n\t\t}\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`Failed to evaluate ${resolvedPath}.`,\n\t\t\t\t`Underlying error: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\t\"This is usually a TypeScript syntax error, a missing dependency, or a runtime exception inside the config file. Run the file directly (e.g. `npx tsx neon.ts`) to reproduce.\",\n\t\t\t].join(\"\\n\"),\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tconst exported = extractDefaultExport(mod);\n\tif (exported === undefined) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t`${resolvedPath} loaded successfully but did not default-export a config.`,\n\t\t\t\t\"Add `export default defineConfig({ ... })` at the bottom of the file. (Named exports are ignored.)\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\t// Run through defineConfig to validate any function the user might have constructed manually.\n\tconst config = defineConfig(exported as Config);\n\treturn { config, resolvedPath };\n}\n\nfunction resolveExplicitPath(input: string, cwd?: string): string {\n\tconst base = resolve(cwd ?? process.cwd());\n\tconst abs = isAbsolute(input) ? input : resolve(base, input);\n\tif (!existsSync(abs)) {\n\t\tthrow new ConfigLoadError(\n\t\t\t`Config file not found at ${abs}. The path was resolved from \\`${input}\\` against ${base}.`,\n\t\t);\n\t}\n\tconst s = statSync(abs);\n\tif (!s.isFile()) {\n\t\tthrow new ConfigLoadError(\n\t\t\t`Config path ${abs} is a directory, not a file. Pass a path to the file itself (e.g. ./neon.ts).`,\n\t\t);\n\t}\n\treturn abs;\n}\n\nfunction findDefaultConfig(\n\tcwd: string | undefined,\n\tstopAt: string | undefined,\n): string | null {\n\tlet current = resolve(cwd ?? process.cwd());\n\tconst stop = resolve(stopAt ?? homedir());\n\tlet lastSeen: string | null = null;\n\n\twhile (true) {\n\t\tfor (const name of DEFAULT_CONFIG_FILENAMES) {\n\t\t\tconst candidate = resolve(current, name);\n\t\t\tif (existsSync(candidate) && safeIsFile(candidate))\n\t\t\t\treturn candidate;\n\t\t}\n\n\t\t// `.git` is the canonical repo-root marker. `package.json` is deliberately *not*\n\t\t// a stop: monorepos lift `neon.ts` above sub-package package.jsons.\n\t\tif (existsSync(resolve(current, \".git\"))) return null;\n\t\tif (current === stop) return null;\n\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parent === lastSeen) return null;\n\t\tlastSeen = current;\n\t\tcurrent = parent;\n\t}\n}\n\nasync function importModule(\n\tabsPath: string,\n\tforceJiti = false,\n): Promise<unknown> {\n\tconst lower = absPath.toLowerCase();\n\tconst needsJiti =\n\t\tforceJiti ||\n\t\tlower.endsWith(\".ts\") ||\n\t\tlower.endsWith(\".mts\") ||\n\t\tlower.endsWith(\".cts\");\n\n\tif (!needsJiti) {\n\t\treturn import(pathToFileURL(absPath).href);\n\t}\n\n\tconst jitiModule: unknown = await import(\"jiti\");\n\tconst createJiti = extractCreateJiti(jitiModule);\n\tif (!createJiti) {\n\t\tthrow new ConfigLoadError(\n\t\t\t[\n\t\t\t\t\"jiti is required to load TypeScript config files but could not be initialised.\",\n\t\t\t\t\"Reinstall the package dependencies (`pnpm install` / `npm install`) — jiti is a runtime dependency of @neon/config.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\tconst jiti = createJiti(pathToFileURL(absPath).href, {\n\t\tinteropDefault: true,\n\t\tmoduleCache: false,\n\t});\n\treturn jiti.import(absPath);\n}\n\nfunction extractCreateJiti(\n\tmod: unknown,\n): ((id: string, options?: unknown) => JitiInstance) | null {\n\tif (mod === null || typeof mod !== \"object\") return null;\n\tconst obj = mod as Record<string, unknown>;\n\tif (typeof obj.createJiti === \"function\") {\n\t\treturn obj.createJiti as (\n\t\t\tid: string,\n\t\t\toptions?: unknown,\n\t\t) => JitiInstance;\n\t}\n\tconst def = obj.default;\n\tif (def !== null && typeof def === \"object\") {\n\t\tconst defObj = def as Record<string, unknown>;\n\t\tif (typeof defObj.createJiti === \"function\") {\n\t\t\treturn defObj.createJiti as (\n\t\t\t\tid: string,\n\t\t\t\toptions?: unknown,\n\t\t\t) => JitiInstance;\n\t\t}\n\t}\n\treturn null;\n}\n\ninterface JitiInstance {\n\timport(id: string): Promise<unknown>;\n}\n\nfunction extractDefaultExport(mod: unknown): unknown {\n\tif (mod === null || typeof mod !== \"object\") return mod;\n\tconst obj = mod as Record<string, unknown>;\n\tif (\"default\" in obj && obj.default !== undefined) return obj.default;\n\t// No `default` export. If the module itself is a function, treat it as the config —\n\t// that lets tests and advanced users skip the wrapper.\n\t// Otherwise, return `undefined` so the caller surfaces a clear ConfigLoadError.\n\tif (typeof mod === \"function\") return mod;\n\treturn undefined;\n}\n\nfunction safeIsFile(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst UNSET_FUNCTION_ENV_ISSUE =\n\t/^preview\\.functions\\.[^.]+\\.env\\.(.+): Environment variable \"\\1\" for function \".+\" is undefined/;\n\nfunction unsetFunctionEnvKeys(err: unknown): string[] | null {\n\tif (!isPlatformError(err) || err.code !== ErrorCode.InvalidConfig) {\n\t\treturn null;\n\t}\n\tconst issues = platformErrorIssues(err);\n\tif (issues === null || issues.length === 0) return null;\n\tconst keys: string[] = [];\n\tfor (const issue of issues) {\n\t\tconst match = UNSET_FUNCTION_ENV_ISSUE.exec(issue);\n\t\tconst key = match?.[1];\n\t\tif (key === undefined) return null;\n\t\tkeys.push(key);\n\t}\n\treturn keys;\n}\n\nfunction platformErrorIssues(err: unknown): readonly string[] | null {\n\tif (typeof err !== \"object\" || err === null || !(\"issues\" in err)) {\n\t\treturn null;\n\t}\n\tconst { issues } = err;\n\tif (\n\t\t!Array.isArray(issues) ||\n\t\tissues.some((issue) => typeof issue !== \"string\")\n\t) {\n\t\treturn null;\n\t}\n\treturn issues;\n}\n\nasync function withPlaceholderFunctionEnv<T>(\n\trun: () => Promise<T>,\n): Promise<T> {\n\t// Validation reports config keys, not source process.env names, so the reload\n\t// must cover every unset lookup.\n\tconst original = process.env;\n\tconst proxy = new Proxy(original, {\n\t\tget(target, prop, receiver) {\n\t\t\tif (typeof prop === \"symbol\") {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\t\t\tconst value = Reflect.get(target, prop, receiver);\n\t\t\treturn value === undefined ? \"\" : value;\n\t\t},\n\t});\n\tprocess.env = proxy;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tprocess.env = original;\n\t}\n}\n\nconst CONFIG_LOAD_LOCK = Symbol.for(\"@neon/config loadConfigFromFile lock\");\n\ntype ConfigLoadLock = { chain: Promise<unknown> };\n\nfunction configLoadLock(): ConfigLoadLock {\n\tconst g = globalThis as typeof globalThis & {\n\t\t[CONFIG_LOAD_LOCK]?: ConfigLoadLock;\n\t};\n\tconst lock = g[CONFIG_LOAD_LOCK] ?? { chain: Promise.resolve() };\n\tg[CONFIG_LOAD_LOCK] = lock;\n\treturn lock;\n}\n\nasync function withSerializedConfigLoad<T>(run: () => Promise<T>): Promise<T> {\n\tconst lock = configLoadLock();\n\tconst next = lock.chain.then(run, run);\n\tlock.chain = next.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\treturn next;\n}\n\nfunction withoutFunctionEnvKeys(\n\tconfig: Config,\n\tkeys: ReadonlySet<string>,\n): Config {\n\tconst functions = config.preview?.functions;\n\tif (!functions) return config;\n\tconst nextFunctions: Record<string, FunctionDef> = {};\n\tfor (const [slug, fn] of Object.entries(functions)) {\n\t\tif (!fn.env) {\n\t\t\tnextFunctions[slug] = fn;\n\t\t\tcontinue;\n\t\t}\n\t\tconst env = Object.fromEntries(\n\t\t\tObject.entries(fn.env).filter(([key]) => !keys.has(key)),\n\t\t);\n\t\tnextFunctions[slug] = { ...fn, env };\n\t}\n\treturn Object.freeze({\n\t\t...config,\n\t\tpreview: { ...config.preview, functions: nextFunctions },\n\t});\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAiRU,uBAAA;;EAAA,aAAA,CAAA,EAAA,MAAA;AAeV;AA4CC;AAeD;AAAmC;AAChB;AAAR;AACF,iBA7DO,iBAAA,CA6DP,OAAA,EAAA;EACE,MAAA,EAAA,MAAA;EAAR,OAAA,CAAA,EAAA,MAAA;EAAO;AAk9BV;AAsGA;AA6DA;AAoBA;EAAuC,aAAA,CAAA,EAAA;IAAQ,WAAA,CAAA,EAAA,MAAA;IAAsB,cAAA,CAAA,EAAA,MAAA;IAAQ,UAAA,CAAA,EAAA,MAAA;EAwBvD,CAAA;AAAY,CAAA,CAAA,EAltC9B,OAktC8B;AAAM,UAjrC9B,WAAA,CAirC8B;EAAW,WAAA,EAAA,MAAA;EAAO,cAAA,EAAA,MAAA;;;;;;;;;;iBApqCpC,2BACX,QAAQ,YACV,cACN,QAAQ;;;;;;;;;;;;iBAk9BK,2BAAA;;;;;;;;;;;;iBAsGA,uBAAA;iBA6DA,uBAAA;;IAEZ;;;;;;;;;;;;iBAkBY,uBAAA,QAA+B,sBAAsB;;;;;;;;;;;iBAwB/C,YAAA,MAAkB,WAAW"}
1
+ {"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAkRU,uBAAA;;EAAA,aAAA,CAAA,EAAA,MAAA;AAeV;AA4CC;AAeD;AAAmC;AAChB;AAAR;AACF,iBA7DO,iBAAA,CA6DP,OAAA,EAAA;EACE,MAAA,EAAA,MAAA;EAAR,OAAA,CAAA,EAAA,MAAA;EAAO;AA++BV;AAsGA;AA6DA;AAoBA;EAAuC,aAAA,CAAA,EAAA;IAAQ,WAAA,CAAA,EAAA,MAAA;IAAsB,cAAA,CAAA,EAAA,MAAA;IAAQ,UAAA,CAAA,EAAA,MAAA;EAwBvD,CAAA;AAAY,CAAA,CAAA,EA/uC9B,OA+uC8B;AAAM,UA9sC9B,WAAA,CA8sC8B;EAAW,WAAA,EAAA,MAAA;EAAO,cAAA,EAAA,MAAA;;;;;;;;;;iBAjsCpC,2BACX,QAAQ,YACV,cACN,QAAQ;;;;;;;;;;;;iBA++BK,2BAAA;;;;;;;;;;;;iBAsGA,uBAAA;iBA6DA,uBAAA;;IAEZ;;;;;;;;;;;;iBAkBY,uBAAA,QAA+B,sBAAsB;;;;;;;;;;;iBAwB/C,YAAA,MAAkB,WAAW"}
@@ -3,7 +3,7 @@ import { formatSuspendTimeout, parseSuspendTimeout } from "./duration.js";
3
3
  import { wrapNeonError } from "./wrap-neon-error.js";
4
4
  import { z } from "zod";
5
5
  import { createNeonClient } from "@neon/sdk";
6
- import { createProject, createProjectBranch, createProjectBranchDataApi, getConnectionUri, getNeonAuth, getProject, getProjectBranchDataApi, listProjectBranchDatabases, listProjectBranchRoles, listProjectBranches, listProjectEndpoints, listProjects, updateProject, updateProjectBranch, updateProjectBranchDataApi, updateProjectEndpoint } from "@neon/sdk/raw";
6
+ import { createProject, createProjectBranch, createProjectBranchDataApi, deleteProjectBranchDataApi, getConnectionUri, getNeonAuth, getProject, getProjectBranchDataApi, listProjectBranchDatabases, listProjectBranchRoles, listProjectBranches, listProjectEndpoints, listProjects, updateProject, updateProjectBranch, updateProjectBranchDataApi, updateProjectEndpoint } from "@neon/sdk/raw";
7
7
  //#region src/lib/neon-api-real.ts
8
8
  const DEFAULT_NEON_API_BASE_URL = "https://console.neon.tech/api/v2";
9
9
  /**
@@ -543,6 +543,26 @@ var RealNeonApi = class {
543
543
  mutating: true
544
544
  });
545
545
  }
546
+ async deleteProjectBranchDataApi(projectId, branchId, databaseName) {
547
+ try {
548
+ await this.call(`deleteProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`, async () => {
549
+ unwrap(await deleteProjectBranchDataApi({
550
+ client: this.client,
551
+ path: {
552
+ project_id: projectId,
553
+ branch_id: branchId,
554
+ database_name: databaseName
555
+ }
556
+ }));
557
+ }, {
558
+ projectId,
559
+ mutating: true
560
+ });
561
+ } catch (err) {
562
+ if (err instanceof PlatformError && err.code === ErrorCode.NotFound) return;
563
+ throw err;
564
+ }
565
+ }
546
566
  async listBranchBuckets(projectId, branchId) {
547
567
  try {
548
568
  return await this.call(`listBranchBuckets(${projectId}/${branchId})`, async () => {