neon 4.20.0 → 4.21.1

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.
package/README.md CHANGED
@@ -583,7 +583,7 @@ If you'd rather not keep env vars on disk, inject them at runtime instead with `
583
583
 
584
584
  ## Config as code (`config` / `deploy`)
585
585
 
586
- Describe a branch's desired state in a `neon.ts` policy and reconcile it from the CLI — the Neon equivalent of `terraform status` / `plan` / `apply`. A policy splits into a **static** existential set — top-level `auth` / `dataApi` / `aiGateway` / `functions` / `buckets` (the last three still work under deprecated `preview`) that decide what _exists_ — and a **dynamic** `branch` closure that tunes each branch (compute settings, TTL, protection, `parent`) based on the branch it's evaluated for (`name`, `isDefault`, …):
586
+ Describe a branch's desired state in a `neon.ts` policy and reconcile it from the CLI — the Neon equivalent of `terraform status` / `plan` / `apply`. A policy splits into a **static** existential set — top-level `auth` / `dataApi` / `aiGateway` / `functions` / `buckets` / `triggers` (`aiGateway`, `functions`, and `buckets` still work under deprecated `preview`) that decide what _exists_ — and a **dynamic** `branch` closure that tunes each branch (compute settings, TTL, protection, `parent`) based on the branch it's evaluated for (`name`, `isDefault`, …):
587
587
 
588
588
  ```ts
589
589
  // neon.ts
@@ -967,21 +967,23 @@ All sub-commands honor the [global options](#global-options), including `--outpu
967
967
 
968
968
  ## Function triggers (`triggers`)
969
969
 
970
- `neon triggers` (alias `neon trigger`) manages **scheduled function triggers** on a branch — cron jobs that invoke a Neon Function. Beta. The only trigger type is `schedule`; cron is a five-field UTC expression.
970
+ `neon triggers` (alias `neon trigger`) manages Function triggers on a branch. Types are `schedule` (a five-field UTC cron expression) and `storage_object_created` (an object-storage bucket, with an optional object-key prefix).
971
971
 
972
972
  Every sub-command resolves the project through the standard chain (`--project-id`, then the `.neon` context file, then a single-project auto-detect) and the branch through `--branch <id|name>`, the `.neon` pin, or the project's default branch.
973
973
 
974
974
  ```bash
975
975
  neon triggers create --function-slug uptime --name uptime-check --cron '*/15 * * * *'
976
+ neon triggers create --function-slug ingest --name on-upload --bucket assets --prefix 'logos/' --function-path /object
976
977
  neon triggers list
977
978
  neon triggers get trigger-test-123
978
979
  neon triggers update trigger-test-123 --cron '0 3 * * *'
980
+ neon triggers update trigger-storage-123 --bucket assets --prefix 'incoming/'
979
981
  neon triggers enable trigger-test-123
980
982
  neon triggers disable trigger-test-123
981
983
  neon triggers delete trigger-test-123
982
984
  ```
983
985
 
984
- `enable` / `disable` are wrappers over `update --enabled`. List shows `inherited` when the effective config was authored on an ancestor branch.
986
+ `enable` / `disable` are wrappers over `update --enabled`. List shows `inherited` when the effective config was authored on an ancestor branch. `create` takes `--cron` or `--bucket`, not both.
985
987
 
986
988
  ## Branch credentials (`credentials`)
987
989
 
@@ -1010,7 +1012,7 @@ neon inspect db stalled-queries --output json
1010
1012
 
1011
1013
  ## Logs (`logs`)
1012
1014
 
1013
- `neon logs` reads the log records the services on a branch emit — Neon Functions, object storage, and Postgres computes. **Logs require Neon Platform Beta and are currently available only for projects in `aws-us-east-2` and `aws-eu-central-1`.**
1015
+ `neon logs` reads the log records the services on a branch emit — Neon Functions, object storage, and Postgres computes. **Logs require Neon Platform Beta and are currently available only for projects in `aws-us-east-2`, `aws-us-east-1`, `aws-eu-central-1`, and `aws-ap-southeast-1`.**
1014
1016
 
1015
1017
  Every sub-command resolves the project through the standard chain (`--project-id`, then the `.neon` context file, then a single-project auto-detect), and takes `--branch <id|name>`, defaulting to the project's default branch. `logs query` searches the previous hour by default; `logs field-values` searches the previous six hours. The maximum time window is seven days.
1016
1018
 
@@ -16,7 +16,7 @@ var logs_exports = /* @__PURE__ */ __exportAll({
16
16
  handler: () => handler
17
17
  });
18
18
  const LOGS_EPILOG = `
19
- Logs require Neon Platform Beta and are currently available only for projects in aws-us-east-2 and aws-eu-central-1.
19
+ Logs require Neon Platform Beta and are currently available only for projects in aws-us-east-2, aws-us-east-1, aws-eu-central-1, and aws-ap-southeast-1.
20
20
 
21
21
  For more information, visit https://neon.com/docs/reference/neon-cli`;
22
22
  const LOG_SOURCES = [
@@ -100,8 +100,8 @@ function enabledPatch(type, enabled) {
100
100
  enabled
101
101
  };
102
102
  }
103
- function updatePatch(type, props) {
104
- if (type === "schedule") {
103
+ function updatePatch(existing, props) {
104
+ if (existing.type === "schedule") {
105
105
  const body = { type: "schedule" };
106
106
  if (props["function-slug"] !== void 0) body.function_slug = props["function-slug"];
107
107
  if (props.name !== void 0) body.name = props.name;
@@ -115,6 +115,10 @@ function updatePatch(type, props) {
115
115
  if (props.name !== void 0) body.name = props.name;
116
116
  if (props["function-path"] !== void 0) body.function_path = props["function-path"];
117
117
  if (props.enabled !== void 0) body.enabled = props.enabled;
118
+ if (props.bucket !== void 0 || props.prefix !== void 0) body.storage_object_created = {
119
+ bucket_name: props.bucket ?? existing.storage_object_created.bucket_name,
120
+ ...props.prefix !== void 0 ? { prefix: props.prefix } : existing.storage_object_created.prefix !== void 0 ? { prefix: existing.storage_object_created.prefix } : {}
121
+ };
118
122
  return body;
119
123
  }
120
124
  function noFieldsToUpdateMessage(type) {
@@ -127,6 +131,8 @@ function noFieldsToUpdateMessage(type) {
127
131
  ] : [
128
132
  "--function-slug",
129
133
  "--name",
134
+ "--bucket",
135
+ "--prefix",
130
136
  "--function-path",
131
137
  "--enabled"
132
138
  ];
@@ -148,7 +154,7 @@ const builder = (argv) => argv.usage("$0 triggers <sub-command> [options]").opti
148
154
  }).middleware(fillSingleProject).command("list", "List triggers on the branch", (yargs) => yargs, (args) => list(args)).command("get <id>", "Show a trigger", (yargs) => yargs.positional("id", {
149
155
  describe: "Trigger ID",
150
156
  type: "string"
151
- }), (args) => get(args)).command("create", "Create a trigger that invokes a function on a cron schedule", (yargs) => yargs.options({
157
+ }), (args) => get(args)).command("create", "Create a trigger that invokes a function on a cron schedule or when an object is created", (yargs) => yargs.options({
152
158
  "function-slug": {
153
159
  describe: "Slug of the function to invoke",
154
160
  type: "string",
@@ -161,8 +167,15 @@ const builder = (argv) => argv.usage("$0 triggers <sub-command> [options]").opti
161
167
  },
162
168
  cron: {
163
169
  describe: "Five-field UTC cron expression, e.g. '*/15 * * * *'",
164
- type: "string",
165
- demandOption: true
170
+ type: "string"
171
+ },
172
+ bucket: {
173
+ describe: "Object-storage bucket to watch (storage_object_created)",
174
+ type: "string"
175
+ },
176
+ prefix: {
177
+ describe: "Object-key prefix to match (requires --bucket on create)",
178
+ type: "string"
166
179
  },
167
180
  "function-path": {
168
181
  describe: "Path the invocation is sent to (default '/')",
@@ -188,6 +201,14 @@ const builder = (argv) => argv.usage("$0 triggers <sub-command> [options]").opti
188
201
  describe: "Five-field UTC cron expression",
189
202
  type: "string"
190
203
  },
204
+ bucket: {
205
+ describe: "Object-storage bucket to watch (storage_object_created)",
206
+ type: "string"
207
+ },
208
+ prefix: {
209
+ describe: "Object-key prefix to match",
210
+ type: "string"
211
+ },
191
212
  "function-path": {
192
213
  describe: "Path the invocation is sent to",
193
214
  type: "string"
@@ -221,23 +242,47 @@ const get = async (props) => {
221
242
  };
222
243
  const create = async (props) => {
223
244
  const branchId = await branchIdFromProps(props);
224
- const body = {
225
- type: "schedule",
226
- function_slug: props["function-slug"],
227
- name: props.name,
228
- schedule: { cron: props.cron }
229
- };
230
- if (props["function-path"] !== void 0) body.function_path = props["function-path"];
231
- if (props.enabled !== void 0) body.enabled = props.enabled;
245
+ const body = createBody(props);
232
246
  const { data } = await retryOnLock(() => props.apiClient.createProjectBranchTrigger(props.projectId, branchId, body));
233
247
  writeTrigger(props, data.trigger);
234
248
  };
249
+ function createBody(props) {
250
+ if (props.cron !== void 0 && props.bucket !== void 0) throw new Error("Pass --cron or --bucket, not both.");
251
+ if (props.prefix !== void 0 && props.bucket === void 0) throw new Error("--prefix requires --bucket.");
252
+ if (props.cron !== void 0) {
253
+ const body = {
254
+ type: "schedule",
255
+ function_slug: props["function-slug"],
256
+ name: props.name,
257
+ schedule: { cron: props.cron }
258
+ };
259
+ if (props["function-path"] !== void 0) body.function_path = props["function-path"];
260
+ if (props.enabled !== void 0) body.enabled = props.enabled;
261
+ return body;
262
+ }
263
+ if (props.bucket !== void 0) {
264
+ const body = {
265
+ type: "storage_object_created",
266
+ function_slug: props["function-slug"],
267
+ name: props.name,
268
+ storage_object_created: {
269
+ bucket_name: props.bucket,
270
+ ...props.prefix !== void 0 ? { prefix: props.prefix } : {}
271
+ }
272
+ };
273
+ if (props["function-path"] !== void 0) body.function_path = props["function-path"];
274
+ if (props.enabled !== void 0) body.enabled = props.enabled;
275
+ return body;
276
+ }
277
+ throw new Error("Pass --cron for a schedule trigger, or --bucket for a storage_object_created trigger.");
278
+ }
235
279
  const update = async (props) => {
236
280
  const branchId = await branchIdFromProps(props);
237
281
  const { data: existing } = await withTriggerNotFound(props.id, branchId, () => props.apiClient.getProjectBranchTrigger(props.projectId, branchId, props.id));
238
282
  const trigger = existing.trigger;
239
283
  if (props.cron !== void 0 && trigger.type !== "schedule") throw new Error(`Trigger ${props.id} is type ${trigger.type}; --cron applies to schedule triggers.`);
240
- const body = updatePatch(trigger.type, props);
284
+ if ((props.bucket !== void 0 || props.prefix !== void 0) && trigger.type !== "storage_object_created") throw new Error(`Trigger ${props.id} is type ${trigger.type}; --bucket and --prefix apply to storage_object_created triggers.`);
285
+ const body = updatePatch(trigger, props);
241
286
  if (Object.keys(body).filter((k) => k !== "type").length === 0) throw new Error(noFieldsToUpdateMessage(trigger.type));
242
287
  const { data } = await withTriggerNotFound(props.id, branchId, () => retryOnLock(() => props.apiClient.updateProjectBranchTrigger(props.projectId, branchId, props.id, body)));
243
288
  writeTrigger(props, data.trigger);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "4.20.0",
3
+ "version": "4.21.1",
4
4
  "description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -63,9 +63,9 @@
63
63
  "yaml": "^2.9.0",
64
64
  "yargs": "17.7.2",
65
65
  "yoctocolors": "^2.1.2",
66
- "@neon/config-runtime": "1.5.0",
67
- "@neon/sdk": "6.0.0",
68
- "@neon/config": "1.6.0"
66
+ "@neon/config": "1.7.1",
67
+ "@neon/config-runtime": "1.6.1",
68
+ "@neon/sdk": "6.0.0"
69
69
  },
70
70
  "optionalDependencies": {
71
71
  "@napi-rs/keyring": "1.3.0",
@@ -98,7 +98,7 @@
98
98
  "typescript": "^5.9.0",
99
99
  "vitest": "^3.0.9",
100
100
  "@neon-internals/cli-core": "0.0.0",
101
- "@neon-internals/env-core": "0.0.18",
101
+ "@neon-internals/env-core": "0.0.20",
102
102
  "@neon/e2e-harness": "0.0.0",
103
103
  "@neon/functions": "0.11.0"
104
104
  },