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 +6 -4
- package/dist/commands/logs.js +1 -1
- package/dist/commands/triggers.js +59 -14
- package/package.json +5 -5
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` (
|
|
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
|
|
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`
|
|
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
|
|
package/dist/commands/logs.js
CHANGED
|
@@ -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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
67
|
-
"@neon/
|
|
68
|
-
"@neon/
|
|
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.
|
|
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
|
},
|