browse 0.10.0 → 0.11.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.
- package/dist/commands/cloud/secrets/create.js +33 -0
- package/dist/commands/cloud/secrets/delete.js +23 -0
- package/dist/commands/cloud/secrets/get.js +24 -0
- package/dist/commands/cloud/secrets/list.js +20 -0
- package/dist/commands/cloud/secrets/update.js +34 -0
- package/dist/commands/functions/secrets/attach.js +27 -0
- package/dist/commands/functions/secrets/detach.js +27 -0
- package/dist/commands/functions/secrets/list.js +28 -0
- package/dist/lib/cloud/api.js +3 -0
- package/dist/lib/secrets/api.js +60 -0
- package/dist/lib/secrets/flags.js +36 -0
- package/dist/lib/secrets/input.js +33 -0
- package/dist/lib/secrets/seal.js +30 -0
- package/dist/lib/templates/api.js +1 -0
- package/dist/lib/templates/scaffold.js +29 -16
- package/oclif.manifest.json +534 -42
- package/package.json +10 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { createSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
import { readSecretValue } from "../../../lib/secrets/input.js";
|
|
6
|
+
import { secretInputFlags } from "../../../lib/secrets/flags.js";
|
|
7
|
+
import { outputJson } from "../../../lib/output.js";
|
|
8
|
+
export default class SecretsCreate extends BrowseCommand {
|
|
9
|
+
static description = "Create a project secret. Encrypts the value locally with the project public key.";
|
|
10
|
+
static examples = [
|
|
11
|
+
"browse cloud secrets create SERVICE_TOKEN",
|
|
12
|
+
"browse cloud secrets create SERVICE_TOKEN --env MY_SERVICE_TOKEN",
|
|
13
|
+
"browse cloud secrets create SERVICE_TOKEN --stdin < ./secret.txt",
|
|
14
|
+
];
|
|
15
|
+
static args = {
|
|
16
|
+
key: Args.string({
|
|
17
|
+
description: "Name exposed in the function context.secrets object.",
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = { ...apiCommonFlags, ...secretInputFlags };
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(SecretsCreate);
|
|
24
|
+
const options = toApiOptions(flags);
|
|
25
|
+
const value = await readSecretValue({ stdin: flags.stdin, env: flags.env });
|
|
26
|
+
try {
|
|
27
|
+
outputJson(await createSecret(options, args.key, value));
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
value.fill(0);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { deleteSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
export default class SecretsDelete extends BrowseCommand {
|
|
6
|
+
static description = "Delete a project secret.";
|
|
7
|
+
static examples = [
|
|
8
|
+
"browse cloud secrets delete <secretId>",
|
|
9
|
+
"browse cloud secrets delete d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
secretId: Args.string({
|
|
13
|
+
description: "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
static flags = { ...apiCommonFlags };
|
|
18
|
+
async run() {
|
|
19
|
+
const { args, flags } = await this.parse(SecretsDelete);
|
|
20
|
+
const options = toApiOptions(flags);
|
|
21
|
+
await deleteSecret(options, args.secretId);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { getSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
import { outputJson } from "../../../lib/output.js";
|
|
6
|
+
export default class SecretsGet extends BrowseCommand {
|
|
7
|
+
static description = "Get project secret metadata. Does not return the secret value.";
|
|
8
|
+
static examples = [
|
|
9
|
+
"browse cloud secrets get <secretId>",
|
|
10
|
+
"browse cloud secrets get d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
secretId: Args.string({
|
|
14
|
+
description: "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
15
|
+
required: true,
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static flags = { ...apiCommonFlags };
|
|
19
|
+
async run() {
|
|
20
|
+
const { args, flags } = await this.parse(SecretsGet);
|
|
21
|
+
const options = toApiOptions(flags);
|
|
22
|
+
outputJson(await getSecret(options, args.secretId));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BrowseCommand } from "../../../base.js";
|
|
2
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
3
|
+
import { listSecrets } from "../../../lib/secrets/api.js";
|
|
4
|
+
import { listSecretsFlags, toListSecretsOptions, } from "../../../lib/secrets/flags.js";
|
|
5
|
+
import { outputJson } from "../../../lib/output.js";
|
|
6
|
+
export default class SecretsList extends BrowseCommand {
|
|
7
|
+
static description = "List project secret metadata with cursor pagination.";
|
|
8
|
+
static examples = [
|
|
9
|
+
"browse cloud secrets list",
|
|
10
|
+
"browse cloud secrets list --start-at 2026-01-01T00:00:00Z",
|
|
11
|
+
"browse cloud secrets list --start-at 2026-01-01T00:00:00Z --end-at 2026-02-01T00:00:00Z",
|
|
12
|
+
"browse cloud secrets list --limit 10",
|
|
13
|
+
];
|
|
14
|
+
static flags = { ...apiCommonFlags, ...listSecretsFlags };
|
|
15
|
+
async run() {
|
|
16
|
+
const { flags } = await this.parse(SecretsList);
|
|
17
|
+
const options = toApiOptions(flags);
|
|
18
|
+
outputJson(await listSecrets(options, toListSecretsOptions(flags)));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { updateSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
import { readSecretValue } from "../../../lib/secrets/input.js";
|
|
6
|
+
import { secretInputFlags } from "../../../lib/secrets/flags.js";
|
|
7
|
+
import { outputJson } from "../../../lib/output.js";
|
|
8
|
+
export default class SecretsUpdate extends BrowseCommand {
|
|
9
|
+
static description = "Replace a secret value, encrypting it locally with the current project public key.";
|
|
10
|
+
static examples = [
|
|
11
|
+
"browse cloud secrets update <secretId>",
|
|
12
|
+
"browse cloud secrets update d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
13
|
+
"browse cloud secrets update <secretId> --env MY_SERVICE_TOKEN",
|
|
14
|
+
"browse cloud secrets update <secretId> --stdin < ./secret.txt",
|
|
15
|
+
];
|
|
16
|
+
static args = {
|
|
17
|
+
secretId: Args.string({
|
|
18
|
+
description: "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = { ...apiCommonFlags, ...secretInputFlags };
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(SecretsUpdate);
|
|
25
|
+
const options = toApiOptions(flags);
|
|
26
|
+
const value = await readSecretValue({ stdin: flags.stdin, env: flags.env });
|
|
27
|
+
try {
|
|
28
|
+
outputJson(await updateSecret(options, args.secretId, value));
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
value.fill(0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { attachFunctionSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
export default class FunctionSecretsAttach extends BrowseCommand {
|
|
6
|
+
static description = "Attach an existing project secret to a function.";
|
|
7
|
+
static examples = [
|
|
8
|
+
"browse functions secrets attach <functionId> <secretId>",
|
|
9
|
+
"browse functions secrets attach 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041 d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
functionId: Args.string({
|
|
13
|
+
description: "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
secretId: Args.string({
|
|
17
|
+
description: "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = { ...apiCommonFlags };
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(FunctionSecretsAttach);
|
|
24
|
+
const options = toApiOptions(flags);
|
|
25
|
+
await attachFunctionSecret(options, args.functionId, args.secretId);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { detachFunctionSecret } from "../../../lib/secrets/api.js";
|
|
5
|
+
export default class FunctionSecretsDetach extends BrowseCommand {
|
|
6
|
+
static description = "Detach a secret from a function without deleting the secret.";
|
|
7
|
+
static examples = [
|
|
8
|
+
"browse functions secrets detach <functionId> <secretId>",
|
|
9
|
+
"browse functions secrets detach 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041 d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
functionId: Args.string({
|
|
13
|
+
description: "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
secretId: Args.string({
|
|
17
|
+
description: "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = { ...apiCommonFlags };
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(FunctionSecretsDetach);
|
|
24
|
+
const options = toApiOptions(flags);
|
|
25
|
+
await detachFunctionSecret(options, args.functionId, args.secretId);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { BrowseCommand } from "../../../base.js";
|
|
3
|
+
import { apiCommonFlags, toApiOptions } from "../../../lib/cloud/flags.js";
|
|
4
|
+
import { listFunctionSecrets } from "../../../lib/secrets/api.js";
|
|
5
|
+
import { listSecretsFlags, toListSecretsOptions, } from "../../../lib/secrets/flags.js";
|
|
6
|
+
import { outputJson } from "../../../lib/output.js";
|
|
7
|
+
export default class FunctionSecretsList extends BrowseCommand {
|
|
8
|
+
static description = "List metadata for secrets attached to a function with cursor pagination.";
|
|
9
|
+
static examples = [
|
|
10
|
+
"browse functions secrets list <functionId>",
|
|
11
|
+
"browse functions secrets list 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041",
|
|
12
|
+
"browse functions secrets list <functionId> --start-at 2026-01-01T00:00:00Z",
|
|
13
|
+
"browse functions secrets list <functionId> --start-at 2026-01-01T00:00:00Z --end-at 2026-02-01T00:00:00Z",
|
|
14
|
+
"browse functions secrets list <functionId> --limit 10",
|
|
15
|
+
];
|
|
16
|
+
static args = {
|
|
17
|
+
functionId: Args.string({
|
|
18
|
+
description: "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = { ...apiCommonFlags, ...listSecretsFlags };
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(FunctionSecretsList);
|
|
25
|
+
const options = toApiOptions(flags);
|
|
26
|
+
outputJson(await listFunctionSecrets(options, args.functionId, toListSecretsOptions(flags)));
|
|
27
|
+
}
|
|
28
|
+
}
|
package/dist/lib/cloud/api.js
CHANGED
|
@@ -328,6 +328,9 @@ function resolveCommandFromPathname(pathname) {
|
|
|
328
328
|
if (pathname.startsWith("/v1/extensions")) {
|
|
329
329
|
return "extensions";
|
|
330
330
|
}
|
|
331
|
+
if (pathname.startsWith("/v1/secrets")) {
|
|
332
|
+
return "secrets";
|
|
333
|
+
}
|
|
331
334
|
if (pathname.startsWith("/v1/functions")) {
|
|
332
335
|
return "functions";
|
|
333
336
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { sealSecret } from "./seal.js";
|
|
2
|
+
import { requestBrowserbase, requestBrowserbaseJson } from "../cloud/api.js";
|
|
3
|
+
export function listSecrets(options, query) {
|
|
4
|
+
return requestBrowserbaseJson(options, withQuery("/v1/secrets", query));
|
|
5
|
+
}
|
|
6
|
+
function withQuery(path, query) {
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
for (const [key, value] of Object.entries(query)) {
|
|
9
|
+
if (value !== undefined)
|
|
10
|
+
params.set(key, String(value));
|
|
11
|
+
}
|
|
12
|
+
const search = params.toString();
|
|
13
|
+
return search ? `${path}?${search}` : path;
|
|
14
|
+
}
|
|
15
|
+
export function getSecret(options, secretId) {
|
|
16
|
+
return requestBrowserbaseJson(options, secretPath(secretId));
|
|
17
|
+
}
|
|
18
|
+
export async function deleteSecret(options, secretId) {
|
|
19
|
+
await requestBrowserbase(options, secretPath(secretId), { method: "DELETE" });
|
|
20
|
+
}
|
|
21
|
+
function secretPath(id) {
|
|
22
|
+
return `/v1/secrets/${encodeURIComponent(id)}`;
|
|
23
|
+
}
|
|
24
|
+
export async function createSecret(options, secretKey, value) {
|
|
25
|
+
const sealed = await encryptValue(options, value);
|
|
26
|
+
return requestBrowserbaseJson(options, "/v1/secrets", {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "content-type": "application/json" },
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
secretKey,
|
|
31
|
+
...sealed,
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function updateSecret(options, secretId, value) {
|
|
36
|
+
const sealed = await encryptValue(options, value);
|
|
37
|
+
return requestBrowserbaseJson(options, secretPath(secretId), {
|
|
38
|
+
method: "PATCH",
|
|
39
|
+
headers: { "content-type": "application/json" },
|
|
40
|
+
body: JSON.stringify(sealed),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async function encryptValue(options, value) {
|
|
44
|
+
const keypair = await requestBrowserbaseJson(options, "/v1/secrets/keypair");
|
|
45
|
+
const sealedSecretValue = await sealSecret(keypair.publicKey, value);
|
|
46
|
+
return { keypairId: keypair.id, sealedSecretValue };
|
|
47
|
+
}
|
|
48
|
+
export async function attachFunctionSecret(options, functionId, secretId) {
|
|
49
|
+
await requestBrowserbase(options, `/v1/functions/${encodeURIComponent(functionId)}/secrets`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: { "content-type": "application/json" },
|
|
52
|
+
body: JSON.stringify({ secretId }),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export async function detachFunctionSecret(options, functionId, secretId) {
|
|
56
|
+
await requestBrowserbase(options, `/v1/functions/${encodeURIComponent(functionId)}/secrets/${encodeURIComponent(secretId)}`, { method: "DELETE" });
|
|
57
|
+
}
|
|
58
|
+
export function listFunctionSecrets(options, functionId, query) {
|
|
59
|
+
return requestBrowserbaseJson(options, withQuery(`/v1/functions/${encodeURIComponent(functionId)}/secrets`, query));
|
|
60
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
export const listSecretsFlags = {
|
|
3
|
+
limit: Flags.integer({
|
|
4
|
+
min: 1,
|
|
5
|
+
max: 1000,
|
|
6
|
+
description: "Maximum results per page (API default: 20).",
|
|
7
|
+
}),
|
|
8
|
+
cursor: Flags.string({
|
|
9
|
+
description: "nextCursor from the previous page. Keep the same filters.",
|
|
10
|
+
}),
|
|
11
|
+
"start-at": Flags.string({
|
|
12
|
+
description: "Include secrets created on or after this RFC 3339 timestamp.",
|
|
13
|
+
}),
|
|
14
|
+
"end-at": Flags.string({
|
|
15
|
+
description: "Include secrets created on or before this RFC 3339 timestamp.",
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
export function toListSecretsOptions(flags) {
|
|
19
|
+
return {
|
|
20
|
+
limit: flags.limit,
|
|
21
|
+
cursor: flags.cursor,
|
|
22
|
+
startAt: flags["start-at"],
|
|
23
|
+
endAt: flags["end-at"],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export const secretInputFlags = {
|
|
27
|
+
env: Flags.string({
|
|
28
|
+
description: "Read the secret value from the named environment variable.",
|
|
29
|
+
helpValue: "VARIABLE_NAME",
|
|
30
|
+
exclusive: ["stdin"],
|
|
31
|
+
}),
|
|
32
|
+
stdin: Flags.boolean({
|
|
33
|
+
description: "Read the exact secret value from stdin, preserving whitespace.",
|
|
34
|
+
exclusive: ["env"],
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import password from "@inquirer/password";
|
|
2
|
+
import { fail } from "../errors.js";
|
|
3
|
+
export async function readSecretValue(options) {
|
|
4
|
+
if (options.env !== undefined) {
|
|
5
|
+
if (options.stdin)
|
|
6
|
+
fail("--env and --stdin cannot be used together.");
|
|
7
|
+
if (!options.env)
|
|
8
|
+
fail("--env requires an environment variable name.");
|
|
9
|
+
const value = Object.prototype.hasOwnProperty.call(process.env, options.env)
|
|
10
|
+
? process.env[options.env]
|
|
11
|
+
: undefined;
|
|
12
|
+
if (value === undefined)
|
|
13
|
+
fail("The environment variable selected by --env is not set.");
|
|
14
|
+
return Buffer.from(value, "utf8");
|
|
15
|
+
}
|
|
16
|
+
if (options.stdin) {
|
|
17
|
+
if (process.stdin.isTTY)
|
|
18
|
+
fail("--stdin requires piped input or file redirection.");
|
|
19
|
+
const chunks = [];
|
|
20
|
+
for await (const chunk of process.stdin) {
|
|
21
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
22
|
+
}
|
|
23
|
+
return Buffer.concat(chunks);
|
|
24
|
+
}
|
|
25
|
+
if (!process.stdin.isTTY)
|
|
26
|
+
fail("Use --stdin for piped input or --env to read an environment variable.");
|
|
27
|
+
try {
|
|
28
|
+
return Buffer.from(await password({ message: "Secret value:" }, { output: process.stderr }), "utf8");
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
fail("Secret input cancelled.");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Aes256Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
2
|
+
import { DhkemX25519HkdfSha256 } from "@hpke/dhkem-x25519";
|
|
3
|
+
import { fail } from "../errors.js";
|
|
4
|
+
export async function sealSecret(publicKey, value) {
|
|
5
|
+
if (typeof publicKey !== "string") {
|
|
6
|
+
fail("The secrets API returned an invalid X25519 public key.");
|
|
7
|
+
}
|
|
8
|
+
const rawKey = Buffer.from(publicKey, "base64");
|
|
9
|
+
if (rawKey.length !== 32 || rawKey.toString("base64") !== publicKey) {
|
|
10
|
+
fail("The secrets API returned an invalid X25519 public key.");
|
|
11
|
+
}
|
|
12
|
+
const suite = new CipherSuite({
|
|
13
|
+
kem: new DhkemX25519HkdfSha256(),
|
|
14
|
+
kdf: new HkdfSha256(),
|
|
15
|
+
aead: new Aes256Gcm(),
|
|
16
|
+
});
|
|
17
|
+
try {
|
|
18
|
+
const recipientPublicKey = await suite.kem.deserializePublicKey(new Uint8Array(rawKey).buffer);
|
|
19
|
+
const sender = await suite.createSenderContext({ recipientPublicKey });
|
|
20
|
+
const ciphertext = await sender.seal(new Uint8Array(value).buffer);
|
|
21
|
+
// Go's crypto/hpke.Open expects the encapsulated key followed by ciphertext.
|
|
22
|
+
return Buffer.concat([
|
|
23
|
+
Buffer.from(sender.enc),
|
|
24
|
+
Buffer.from(ciphertext),
|
|
25
|
+
]).toString("base64");
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
fail("Failed to encrypt the secret with the project's public key.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -107,6 +107,7 @@ function parseTemplate(payload, context) {
|
|
|
107
107
|
description: optionalString(payload.description, context, "description"),
|
|
108
108
|
descriptionTitle: optionalString(payload.descriptionTitle, context, "descriptionTitle"),
|
|
109
109
|
source: optionalString(payload.source, context, "source"),
|
|
110
|
+
sourcePath: optionalString(payload.sourcePath, context, "sourcePath"),
|
|
110
111
|
category: optionalStringArray(payload.category, context, "category"),
|
|
111
112
|
tags: optionalStringArray(payload.tags, context, "tags"),
|
|
112
113
|
commands: optionalStringArray(payload.commands, context, "commands"),
|
|
@@ -28,18 +28,15 @@ export async function cloneTemplate(options) {
|
|
|
28
28
|
const parentDir = dirname(dest);
|
|
29
29
|
const projectName = basename(dest);
|
|
30
30
|
const scaffolder = getScaffolder(language);
|
|
31
|
+
// create-browser-app identifies a template by its final source directory.
|
|
32
|
+
const scaffolderTemplate = basename(options.template.sourcePath || options.template.slug);
|
|
31
33
|
await mkdir(parentDir, { recursive: true });
|
|
32
34
|
const existingEntries = await getDirectoryEntryNames(parentDir);
|
|
33
35
|
if (!options.quiet) {
|
|
34
36
|
console.log(`Scaffolding ${language}/${options.template.slug} into ${dest}...`);
|
|
35
37
|
}
|
|
36
38
|
try {
|
|
37
|
-
runCommand(scaffolder.command, [
|
|
38
|
-
...scaffolder.argsPrefix,
|
|
39
|
-
projectName,
|
|
40
|
-
"--template",
|
|
41
|
-
options.template.slug,
|
|
42
|
-
], parentDir);
|
|
39
|
+
runCommand(scaffolder.command, [...scaffolder.argsPrefix, projectName, "--template", scaffolderTemplate], parentDir);
|
|
43
40
|
const createdDir = await findCreatedProjectDir(parentDir, existingEntries, projectName);
|
|
44
41
|
if (!createdDir) {
|
|
45
42
|
throw new Error(`Scaffolder did not create a project directory in ${parentDir}.`);
|
|
@@ -151,22 +148,23 @@ async function findCreatedProjectDir(parentDir, existingEntries, requestedName)
|
|
|
151
148
|
}
|
|
152
149
|
return null;
|
|
153
150
|
}
|
|
154
|
-
async function buildNextSteps(dest, displayPath, language) {
|
|
151
|
+
export async function buildNextSteps(dest, displayPath, language) {
|
|
155
152
|
const nextSteps = [`cd ${displayPath}`];
|
|
156
153
|
if (language === "typescript") {
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
const packageJson = await readPackageJson(dest);
|
|
155
|
+
const packageManager = resolvePackageManager(packageJson?.packageManager);
|
|
156
|
+
if (packageJson) {
|
|
157
|
+
nextSteps.push(`${packageManager} install`);
|
|
159
158
|
}
|
|
160
159
|
if (existsSync(join(dest, ".env.example"))) {
|
|
161
160
|
nextSteps.push("cp .env.example .env");
|
|
162
161
|
}
|
|
163
|
-
const packageJson = await readPackageJson(dest);
|
|
164
162
|
if (packageJson?.scripts?.dev) {
|
|
165
|
-
nextSteps.push("
|
|
163
|
+
nextSteps.push(runPackageScript(packageManager, "dev"));
|
|
166
164
|
return nextSteps;
|
|
167
165
|
}
|
|
168
166
|
if (packageJson?.scripts?.start) {
|
|
169
|
-
nextSteps.push("
|
|
167
|
+
nextSteps.push(runPackageScript(packageManager, "start"));
|
|
170
168
|
return nextSteps;
|
|
171
169
|
}
|
|
172
170
|
if (existsSync(join(dest, "index.ts"))) {
|
|
@@ -174,17 +172,19 @@ async function buildNextSteps(dest, displayPath, language) {
|
|
|
174
172
|
}
|
|
175
173
|
return nextSteps;
|
|
176
174
|
}
|
|
177
|
-
|
|
175
|
+
const hasPyproject = existsSync(join(dest, "pyproject.toml"));
|
|
176
|
+
const hasRequirements = existsSync(join(dest, "requirements.txt"));
|
|
177
|
+
if (hasPyproject) {
|
|
178
178
|
nextSteps.push("uv sync");
|
|
179
179
|
}
|
|
180
|
-
else if (
|
|
181
|
-
nextSteps.push("pip install -r requirements.txt");
|
|
180
|
+
else if (hasRequirements) {
|
|
181
|
+
nextSteps.push("uv venv && uv pip install -r requirements.txt");
|
|
182
182
|
}
|
|
183
183
|
if (existsSync(join(dest, ".env.example"))) {
|
|
184
184
|
nextSteps.push("cp .env.example .env");
|
|
185
185
|
}
|
|
186
186
|
if (existsSync(join(dest, "main.py"))) {
|
|
187
|
-
nextSteps.push("python main.py");
|
|
187
|
+
nextSteps.push("uv run python main.py");
|
|
188
188
|
}
|
|
189
189
|
return nextSteps;
|
|
190
190
|
}
|
|
@@ -201,3 +201,16 @@ async function readPackageJson(dest) {
|
|
|
201
201
|
return null;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
+
function resolvePackageManager(packageManager) {
|
|
205
|
+
const name = packageManager?.split("@")[0];
|
|
206
|
+
if (name === "bun" || name === "pnpm" || name === "yarn") {
|
|
207
|
+
return name;
|
|
208
|
+
}
|
|
209
|
+
return "npm";
|
|
210
|
+
}
|
|
211
|
+
function runPackageScript(packageManager, script) {
|
|
212
|
+
if (packageManager === "npm" || packageManager === "bun") {
|
|
213
|
+
return `${packageManager} run ${script}`;
|
|
214
|
+
}
|
|
215
|
+
return `${packageManager} ${script}`;
|
|
216
|
+
}
|
package/oclif.manifest.json
CHANGED
|
@@ -5502,6 +5502,166 @@
|
|
|
5502
5502
|
"update.js"
|
|
5503
5503
|
]
|
|
5504
5504
|
},
|
|
5505
|
+
"cloud:projects:get": {
|
|
5506
|
+
"aliases": [],
|
|
5507
|
+
"args": {
|
|
5508
|
+
"id": {
|
|
5509
|
+
"description": "Project ID.",
|
|
5510
|
+
"name": "id",
|
|
5511
|
+
"required": true
|
|
5512
|
+
}
|
|
5513
|
+
},
|
|
5514
|
+
"description": "Get a project by ID.",
|
|
5515
|
+
"examples": [
|
|
5516
|
+
"browse cloud projects get <project-id>"
|
|
5517
|
+
],
|
|
5518
|
+
"flags": {
|
|
5519
|
+
"api-key": {
|
|
5520
|
+
"description": "Override the Browserbase API key.",
|
|
5521
|
+
"name": "api-key",
|
|
5522
|
+
"hasDynamicHelp": false,
|
|
5523
|
+
"helpValue": "<apiKey>",
|
|
5524
|
+
"multiple": false,
|
|
5525
|
+
"type": "option"
|
|
5526
|
+
},
|
|
5527
|
+
"base-url": {
|
|
5528
|
+
"description": "Override the Browserbase API base URL.",
|
|
5529
|
+
"name": "base-url",
|
|
5530
|
+
"hasDynamicHelp": false,
|
|
5531
|
+
"helpValue": "<baseUrl>",
|
|
5532
|
+
"multiple": false,
|
|
5533
|
+
"type": "option"
|
|
5534
|
+
}
|
|
5535
|
+
},
|
|
5536
|
+
"hasDynamicHelp": false,
|
|
5537
|
+
"hiddenAliases": [],
|
|
5538
|
+
"id": "cloud:projects:get",
|
|
5539
|
+
"pluginAlias": "browse",
|
|
5540
|
+
"pluginName": "browse",
|
|
5541
|
+
"pluginType": "core",
|
|
5542
|
+
"strict": true,
|
|
5543
|
+
"isESM": true,
|
|
5544
|
+
"relativePath": [
|
|
5545
|
+
"dist",
|
|
5546
|
+
"commands",
|
|
5547
|
+
"cloud",
|
|
5548
|
+
"projects",
|
|
5549
|
+
"get.js"
|
|
5550
|
+
]
|
|
5551
|
+
},
|
|
5552
|
+
"cloud:projects:list": {
|
|
5553
|
+
"aliases": [],
|
|
5554
|
+
"args": {},
|
|
5555
|
+
"description": "List projects visible to the current API key.",
|
|
5556
|
+
"examples": [
|
|
5557
|
+
"browse cloud projects list",
|
|
5558
|
+
"browse cloud projects list --json"
|
|
5559
|
+
],
|
|
5560
|
+
"flags": {
|
|
5561
|
+
"api-key": {
|
|
5562
|
+
"description": "Override the Browserbase API key.",
|
|
5563
|
+
"name": "api-key",
|
|
5564
|
+
"hasDynamicHelp": false,
|
|
5565
|
+
"helpValue": "<apiKey>",
|
|
5566
|
+
"multiple": false,
|
|
5567
|
+
"type": "option"
|
|
5568
|
+
},
|
|
5569
|
+
"base-url": {
|
|
5570
|
+
"description": "Override the Browserbase API base URL.",
|
|
5571
|
+
"name": "base-url",
|
|
5572
|
+
"hasDynamicHelp": false,
|
|
5573
|
+
"helpValue": "<baseUrl>",
|
|
5574
|
+
"multiple": false,
|
|
5575
|
+
"type": "option"
|
|
5576
|
+
},
|
|
5577
|
+
"format": {
|
|
5578
|
+
"description": "Output format. Defaults to table in a terminal and JSON when piped.",
|
|
5579
|
+
"name": "format",
|
|
5580
|
+
"hasDynamicHelp": false,
|
|
5581
|
+
"helpValue": "<format>",
|
|
5582
|
+
"multiple": false,
|
|
5583
|
+
"options": [
|
|
5584
|
+
"table",
|
|
5585
|
+
"json"
|
|
5586
|
+
],
|
|
5587
|
+
"type": "option"
|
|
5588
|
+
},
|
|
5589
|
+
"json": {
|
|
5590
|
+
"description": "Print raw JSON output.",
|
|
5591
|
+
"name": "json",
|
|
5592
|
+
"allowNo": false,
|
|
5593
|
+
"type": "boolean"
|
|
5594
|
+
},
|
|
5595
|
+
"wide": {
|
|
5596
|
+
"description": "Show full table values without truncation.",
|
|
5597
|
+
"name": "wide",
|
|
5598
|
+
"allowNo": false,
|
|
5599
|
+
"type": "boolean"
|
|
5600
|
+
}
|
|
5601
|
+
},
|
|
5602
|
+
"hasDynamicHelp": false,
|
|
5603
|
+
"hiddenAliases": [],
|
|
5604
|
+
"id": "cloud:projects:list",
|
|
5605
|
+
"pluginAlias": "browse",
|
|
5606
|
+
"pluginName": "browse",
|
|
5607
|
+
"pluginType": "core",
|
|
5608
|
+
"strict": true,
|
|
5609
|
+
"isESM": true,
|
|
5610
|
+
"relativePath": [
|
|
5611
|
+
"dist",
|
|
5612
|
+
"commands",
|
|
5613
|
+
"cloud",
|
|
5614
|
+
"projects",
|
|
5615
|
+
"list.js"
|
|
5616
|
+
]
|
|
5617
|
+
},
|
|
5618
|
+
"cloud:projects:usage": {
|
|
5619
|
+
"aliases": [],
|
|
5620
|
+
"args": {
|
|
5621
|
+
"id": {
|
|
5622
|
+
"description": "Project ID.",
|
|
5623
|
+
"name": "id",
|
|
5624
|
+
"required": true
|
|
5625
|
+
}
|
|
5626
|
+
},
|
|
5627
|
+
"description": "Get project usage.",
|
|
5628
|
+
"examples": [
|
|
5629
|
+
"browse cloud projects usage <project-id>"
|
|
5630
|
+
],
|
|
5631
|
+
"flags": {
|
|
5632
|
+
"api-key": {
|
|
5633
|
+
"description": "Override the Browserbase API key.",
|
|
5634
|
+
"name": "api-key",
|
|
5635
|
+
"hasDynamicHelp": false,
|
|
5636
|
+
"helpValue": "<apiKey>",
|
|
5637
|
+
"multiple": false,
|
|
5638
|
+
"type": "option"
|
|
5639
|
+
},
|
|
5640
|
+
"base-url": {
|
|
5641
|
+
"description": "Override the Browserbase API base URL.",
|
|
5642
|
+
"name": "base-url",
|
|
5643
|
+
"hasDynamicHelp": false,
|
|
5644
|
+
"helpValue": "<baseUrl>",
|
|
5645
|
+
"multiple": false,
|
|
5646
|
+
"type": "option"
|
|
5647
|
+
}
|
|
5648
|
+
},
|
|
5649
|
+
"hasDynamicHelp": false,
|
|
5650
|
+
"hiddenAliases": [],
|
|
5651
|
+
"id": "cloud:projects:usage",
|
|
5652
|
+
"pluginAlias": "browse",
|
|
5653
|
+
"pluginName": "browse",
|
|
5654
|
+
"pluginType": "core",
|
|
5655
|
+
"strict": true,
|
|
5656
|
+
"isESM": true,
|
|
5657
|
+
"relativePath": [
|
|
5658
|
+
"dist",
|
|
5659
|
+
"commands",
|
|
5660
|
+
"cloud",
|
|
5661
|
+
"projects",
|
|
5662
|
+
"usage.js"
|
|
5663
|
+
]
|
|
5664
|
+
},
|
|
5505
5665
|
"cloud:extensions:delete": {
|
|
5506
5666
|
"aliases": [],
|
|
5507
5667
|
"args": {
|
|
@@ -5643,18 +5803,88 @@
|
|
|
5643
5803
|
"upload.js"
|
|
5644
5804
|
]
|
|
5645
5805
|
},
|
|
5646
|
-
"cloud:
|
|
5806
|
+
"cloud:secrets:create": {
|
|
5647
5807
|
"aliases": [],
|
|
5648
5808
|
"args": {
|
|
5649
|
-
"
|
|
5650
|
-
"description": "
|
|
5651
|
-
"name": "
|
|
5809
|
+
"key": {
|
|
5810
|
+
"description": "Name exposed in the function context.secrets object.",
|
|
5811
|
+
"name": "key",
|
|
5652
5812
|
"required": true
|
|
5653
5813
|
}
|
|
5654
5814
|
},
|
|
5655
|
-
"description": "
|
|
5815
|
+
"description": "Create a project secret. Encrypts the value locally with the project public key.",
|
|
5656
5816
|
"examples": [
|
|
5657
|
-
"browse cloud
|
|
5817
|
+
"browse cloud secrets create SERVICE_TOKEN",
|
|
5818
|
+
"browse cloud secrets create SERVICE_TOKEN --env MY_SERVICE_TOKEN",
|
|
5819
|
+
"browse cloud secrets create SERVICE_TOKEN --stdin < ./secret.txt"
|
|
5820
|
+
],
|
|
5821
|
+
"flags": {
|
|
5822
|
+
"api-key": {
|
|
5823
|
+
"description": "Override the Browserbase API key.",
|
|
5824
|
+
"name": "api-key",
|
|
5825
|
+
"hasDynamicHelp": false,
|
|
5826
|
+
"helpValue": "<apiKey>",
|
|
5827
|
+
"multiple": false,
|
|
5828
|
+
"type": "option"
|
|
5829
|
+
},
|
|
5830
|
+
"base-url": {
|
|
5831
|
+
"description": "Override the Browserbase API base URL.",
|
|
5832
|
+
"name": "base-url",
|
|
5833
|
+
"hasDynamicHelp": false,
|
|
5834
|
+
"helpValue": "<baseUrl>",
|
|
5835
|
+
"multiple": false,
|
|
5836
|
+
"type": "option"
|
|
5837
|
+
},
|
|
5838
|
+
"env": {
|
|
5839
|
+
"description": "Read the secret value from the named environment variable.",
|
|
5840
|
+
"exclusive": [
|
|
5841
|
+
"stdin"
|
|
5842
|
+
],
|
|
5843
|
+
"name": "env",
|
|
5844
|
+
"hasDynamicHelp": false,
|
|
5845
|
+
"helpValue": "VARIABLE_NAME",
|
|
5846
|
+
"multiple": false,
|
|
5847
|
+
"type": "option"
|
|
5848
|
+
},
|
|
5849
|
+
"stdin": {
|
|
5850
|
+
"description": "Read the exact secret value from stdin, preserving whitespace.",
|
|
5851
|
+
"exclusive": [
|
|
5852
|
+
"env"
|
|
5853
|
+
],
|
|
5854
|
+
"name": "stdin",
|
|
5855
|
+
"allowNo": false,
|
|
5856
|
+
"type": "boolean"
|
|
5857
|
+
}
|
|
5858
|
+
},
|
|
5859
|
+
"hasDynamicHelp": false,
|
|
5860
|
+
"hiddenAliases": [],
|
|
5861
|
+
"id": "cloud:secrets:create",
|
|
5862
|
+
"pluginAlias": "browse",
|
|
5863
|
+
"pluginName": "browse",
|
|
5864
|
+
"pluginType": "core",
|
|
5865
|
+
"strict": true,
|
|
5866
|
+
"isESM": true,
|
|
5867
|
+
"relativePath": [
|
|
5868
|
+
"dist",
|
|
5869
|
+
"commands",
|
|
5870
|
+
"cloud",
|
|
5871
|
+
"secrets",
|
|
5872
|
+
"create.js"
|
|
5873
|
+
]
|
|
5874
|
+
},
|
|
5875
|
+
"cloud:secrets:delete": {
|
|
5876
|
+
"aliases": [],
|
|
5877
|
+
"args": {
|
|
5878
|
+
"secretId": {
|
|
5879
|
+
"description": "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
5880
|
+
"name": "secretId",
|
|
5881
|
+
"required": true
|
|
5882
|
+
}
|
|
5883
|
+
},
|
|
5884
|
+
"description": "Delete a project secret.",
|
|
5885
|
+
"examples": [
|
|
5886
|
+
"browse cloud secrets delete <secretId>",
|
|
5887
|
+
"browse cloud secrets delete d2c4f48f-38e9-4b82-a36a-2b373fd14a65"
|
|
5658
5888
|
],
|
|
5659
5889
|
"flags": {
|
|
5660
5890
|
"api-key": {
|
|
@@ -5676,7 +5906,7 @@
|
|
|
5676
5906
|
},
|
|
5677
5907
|
"hasDynamicHelp": false,
|
|
5678
5908
|
"hiddenAliases": [],
|
|
5679
|
-
"id": "cloud:
|
|
5909
|
+
"id": "cloud:secrets:delete",
|
|
5680
5910
|
"pluginAlias": "browse",
|
|
5681
5911
|
"pluginName": "browse",
|
|
5682
5912
|
"pluginType": "core",
|
|
@@ -5686,17 +5916,67 @@
|
|
|
5686
5916
|
"dist",
|
|
5687
5917
|
"commands",
|
|
5688
5918
|
"cloud",
|
|
5689
|
-
"
|
|
5919
|
+
"secrets",
|
|
5920
|
+
"delete.js"
|
|
5921
|
+
]
|
|
5922
|
+
},
|
|
5923
|
+
"cloud:secrets:get": {
|
|
5924
|
+
"aliases": [],
|
|
5925
|
+
"args": {
|
|
5926
|
+
"secretId": {
|
|
5927
|
+
"description": "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
5928
|
+
"name": "secretId",
|
|
5929
|
+
"required": true
|
|
5930
|
+
}
|
|
5931
|
+
},
|
|
5932
|
+
"description": "Get project secret metadata. Does not return the secret value.",
|
|
5933
|
+
"examples": [
|
|
5934
|
+
"browse cloud secrets get <secretId>",
|
|
5935
|
+
"browse cloud secrets get d2c4f48f-38e9-4b82-a36a-2b373fd14a65"
|
|
5936
|
+
],
|
|
5937
|
+
"flags": {
|
|
5938
|
+
"api-key": {
|
|
5939
|
+
"description": "Override the Browserbase API key.",
|
|
5940
|
+
"name": "api-key",
|
|
5941
|
+
"hasDynamicHelp": false,
|
|
5942
|
+
"helpValue": "<apiKey>",
|
|
5943
|
+
"multiple": false,
|
|
5944
|
+
"type": "option"
|
|
5945
|
+
},
|
|
5946
|
+
"base-url": {
|
|
5947
|
+
"description": "Override the Browserbase API base URL.",
|
|
5948
|
+
"name": "base-url",
|
|
5949
|
+
"hasDynamicHelp": false,
|
|
5950
|
+
"helpValue": "<baseUrl>",
|
|
5951
|
+
"multiple": false,
|
|
5952
|
+
"type": "option"
|
|
5953
|
+
}
|
|
5954
|
+
},
|
|
5955
|
+
"hasDynamicHelp": false,
|
|
5956
|
+
"hiddenAliases": [],
|
|
5957
|
+
"id": "cloud:secrets:get",
|
|
5958
|
+
"pluginAlias": "browse",
|
|
5959
|
+
"pluginName": "browse",
|
|
5960
|
+
"pluginType": "core",
|
|
5961
|
+
"strict": true,
|
|
5962
|
+
"isESM": true,
|
|
5963
|
+
"relativePath": [
|
|
5964
|
+
"dist",
|
|
5965
|
+
"commands",
|
|
5966
|
+
"cloud",
|
|
5967
|
+
"secrets",
|
|
5690
5968
|
"get.js"
|
|
5691
5969
|
]
|
|
5692
5970
|
},
|
|
5693
|
-
"cloud:
|
|
5971
|
+
"cloud:secrets:list": {
|
|
5694
5972
|
"aliases": [],
|
|
5695
5973
|
"args": {},
|
|
5696
|
-
"description": "List
|
|
5974
|
+
"description": "List project secret metadata with cursor pagination.",
|
|
5697
5975
|
"examples": [
|
|
5698
|
-
"browse cloud
|
|
5699
|
-
"browse cloud
|
|
5976
|
+
"browse cloud secrets list",
|
|
5977
|
+
"browse cloud secrets list --start-at 2026-01-01T00:00:00Z",
|
|
5978
|
+
"browse cloud secrets list --start-at 2026-01-01T00:00:00Z --end-at 2026-02-01T00:00:00Z",
|
|
5979
|
+
"browse cloud secrets list --limit 10"
|
|
5700
5980
|
],
|
|
5701
5981
|
"flags": {
|
|
5702
5982
|
"api-key": {
|
|
@@ -5715,34 +5995,38 @@
|
|
|
5715
5995
|
"multiple": false,
|
|
5716
5996
|
"type": "option"
|
|
5717
5997
|
},
|
|
5718
|
-
"
|
|
5719
|
-
"description": "
|
|
5720
|
-
"name": "
|
|
5998
|
+
"limit": {
|
|
5999
|
+
"description": "Maximum results per page (API default: 20).",
|
|
6000
|
+
"name": "limit",
|
|
5721
6001
|
"hasDynamicHelp": false,
|
|
5722
|
-
"helpValue": "<format>",
|
|
5723
6002
|
"multiple": false,
|
|
5724
|
-
"options": [
|
|
5725
|
-
"table",
|
|
5726
|
-
"json"
|
|
5727
|
-
],
|
|
5728
6003
|
"type": "option"
|
|
5729
6004
|
},
|
|
5730
|
-
"
|
|
5731
|
-
"description": "
|
|
5732
|
-
"name": "
|
|
5733
|
-
"
|
|
5734
|
-
"
|
|
6005
|
+
"cursor": {
|
|
6006
|
+
"description": "nextCursor from the previous page. Keep the same filters.",
|
|
6007
|
+
"name": "cursor",
|
|
6008
|
+
"hasDynamicHelp": false,
|
|
6009
|
+
"multiple": false,
|
|
6010
|
+
"type": "option"
|
|
5735
6011
|
},
|
|
5736
|
-
"
|
|
5737
|
-
"description": "
|
|
5738
|
-
"name": "
|
|
5739
|
-
"
|
|
5740
|
-
"
|
|
6012
|
+
"start-at": {
|
|
6013
|
+
"description": "Include secrets created on or after this RFC 3339 timestamp.",
|
|
6014
|
+
"name": "start-at",
|
|
6015
|
+
"hasDynamicHelp": false,
|
|
6016
|
+
"multiple": false,
|
|
6017
|
+
"type": "option"
|
|
6018
|
+
},
|
|
6019
|
+
"end-at": {
|
|
6020
|
+
"description": "Include secrets created on or before this RFC 3339 timestamp.",
|
|
6021
|
+
"name": "end-at",
|
|
6022
|
+
"hasDynamicHelp": false,
|
|
6023
|
+
"multiple": false,
|
|
6024
|
+
"type": "option"
|
|
5741
6025
|
}
|
|
5742
6026
|
},
|
|
5743
6027
|
"hasDynamicHelp": false,
|
|
5744
6028
|
"hiddenAliases": [],
|
|
5745
|
-
"id": "cloud:
|
|
6029
|
+
"id": "cloud:secrets:list",
|
|
5746
6030
|
"pluginAlias": "browse",
|
|
5747
6031
|
"pluginName": "browse",
|
|
5748
6032
|
"pluginType": "core",
|
|
@@ -5752,22 +6036,25 @@
|
|
|
5752
6036
|
"dist",
|
|
5753
6037
|
"commands",
|
|
5754
6038
|
"cloud",
|
|
5755
|
-
"
|
|
6039
|
+
"secrets",
|
|
5756
6040
|
"list.js"
|
|
5757
6041
|
]
|
|
5758
6042
|
},
|
|
5759
|
-
"cloud:
|
|
6043
|
+
"cloud:secrets:update": {
|
|
5760
6044
|
"aliases": [],
|
|
5761
6045
|
"args": {
|
|
5762
|
-
"
|
|
5763
|
-
"description": "Project ID.",
|
|
5764
|
-
"name": "
|
|
6046
|
+
"secretId": {
|
|
6047
|
+
"description": "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
6048
|
+
"name": "secretId",
|
|
5765
6049
|
"required": true
|
|
5766
6050
|
}
|
|
5767
6051
|
},
|
|
5768
|
-
"description": "
|
|
6052
|
+
"description": "Replace a secret value, encrypting it locally with the current project public key.",
|
|
5769
6053
|
"examples": [
|
|
5770
|
-
"browse cloud
|
|
6054
|
+
"browse cloud secrets update <secretId>",
|
|
6055
|
+
"browse cloud secrets update d2c4f48f-38e9-4b82-a36a-2b373fd14a65",
|
|
6056
|
+
"browse cloud secrets update <secretId> --env MY_SERVICE_TOKEN",
|
|
6057
|
+
"browse cloud secrets update <secretId> --stdin < ./secret.txt"
|
|
5771
6058
|
],
|
|
5772
6059
|
"flags": {
|
|
5773
6060
|
"api-key": {
|
|
@@ -5785,11 +6072,31 @@
|
|
|
5785
6072
|
"helpValue": "<baseUrl>",
|
|
5786
6073
|
"multiple": false,
|
|
5787
6074
|
"type": "option"
|
|
6075
|
+
},
|
|
6076
|
+
"env": {
|
|
6077
|
+
"description": "Read the secret value from the named environment variable.",
|
|
6078
|
+
"exclusive": [
|
|
6079
|
+
"stdin"
|
|
6080
|
+
],
|
|
6081
|
+
"name": "env",
|
|
6082
|
+
"hasDynamicHelp": false,
|
|
6083
|
+
"helpValue": "VARIABLE_NAME",
|
|
6084
|
+
"multiple": false,
|
|
6085
|
+
"type": "option"
|
|
6086
|
+
},
|
|
6087
|
+
"stdin": {
|
|
6088
|
+
"description": "Read the exact secret value from stdin, preserving whitespace.",
|
|
6089
|
+
"exclusive": [
|
|
6090
|
+
"env"
|
|
6091
|
+
],
|
|
6092
|
+
"name": "stdin",
|
|
6093
|
+
"allowNo": false,
|
|
6094
|
+
"type": "boolean"
|
|
5788
6095
|
}
|
|
5789
6096
|
},
|
|
5790
6097
|
"hasDynamicHelp": false,
|
|
5791
6098
|
"hiddenAliases": [],
|
|
5792
|
-
"id": "cloud:
|
|
6099
|
+
"id": "cloud:secrets:update",
|
|
5793
6100
|
"pluginAlias": "browse",
|
|
5794
6101
|
"pluginName": "browse",
|
|
5795
6102
|
"pluginType": "core",
|
|
@@ -5799,8 +6106,8 @@
|
|
|
5799
6106
|
"dist",
|
|
5800
6107
|
"commands",
|
|
5801
6108
|
"cloud",
|
|
5802
|
-
"
|
|
5803
|
-
"
|
|
6109
|
+
"secrets",
|
|
6110
|
+
"update.js"
|
|
5804
6111
|
]
|
|
5805
6112
|
},
|
|
5806
6113
|
"cloud:sessions:create": {
|
|
@@ -6300,6 +6607,191 @@
|
|
|
6300
6607
|
"update.js"
|
|
6301
6608
|
]
|
|
6302
6609
|
},
|
|
6610
|
+
"functions:secrets:attach": {
|
|
6611
|
+
"aliases": [],
|
|
6612
|
+
"args": {
|
|
6613
|
+
"functionId": {
|
|
6614
|
+
"description": "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
6615
|
+
"name": "functionId",
|
|
6616
|
+
"required": true
|
|
6617
|
+
},
|
|
6618
|
+
"secretId": {
|
|
6619
|
+
"description": "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
6620
|
+
"name": "secretId",
|
|
6621
|
+
"required": true
|
|
6622
|
+
}
|
|
6623
|
+
},
|
|
6624
|
+
"description": "Attach an existing project secret to a function.",
|
|
6625
|
+
"examples": [
|
|
6626
|
+
"browse functions secrets attach <functionId> <secretId>",
|
|
6627
|
+
"browse functions secrets attach 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041 d2c4f48f-38e9-4b82-a36a-2b373fd14a65"
|
|
6628
|
+
],
|
|
6629
|
+
"flags": {
|
|
6630
|
+
"api-key": {
|
|
6631
|
+
"description": "Override the Browserbase API key.",
|
|
6632
|
+
"name": "api-key",
|
|
6633
|
+
"hasDynamicHelp": false,
|
|
6634
|
+
"helpValue": "<apiKey>",
|
|
6635
|
+
"multiple": false,
|
|
6636
|
+
"type": "option"
|
|
6637
|
+
},
|
|
6638
|
+
"base-url": {
|
|
6639
|
+
"description": "Override the Browserbase API base URL.",
|
|
6640
|
+
"name": "base-url",
|
|
6641
|
+
"hasDynamicHelp": false,
|
|
6642
|
+
"helpValue": "<baseUrl>",
|
|
6643
|
+
"multiple": false,
|
|
6644
|
+
"type": "option"
|
|
6645
|
+
}
|
|
6646
|
+
},
|
|
6647
|
+
"hasDynamicHelp": false,
|
|
6648
|
+
"hiddenAliases": [],
|
|
6649
|
+
"id": "functions:secrets:attach",
|
|
6650
|
+
"pluginAlias": "browse",
|
|
6651
|
+
"pluginName": "browse",
|
|
6652
|
+
"pluginType": "core",
|
|
6653
|
+
"strict": true,
|
|
6654
|
+
"isESM": true,
|
|
6655
|
+
"relativePath": [
|
|
6656
|
+
"dist",
|
|
6657
|
+
"commands",
|
|
6658
|
+
"functions",
|
|
6659
|
+
"secrets",
|
|
6660
|
+
"attach.js"
|
|
6661
|
+
]
|
|
6662
|
+
},
|
|
6663
|
+
"functions:secrets:detach": {
|
|
6664
|
+
"aliases": [],
|
|
6665
|
+
"args": {
|
|
6666
|
+
"functionId": {
|
|
6667
|
+
"description": "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
6668
|
+
"name": "functionId",
|
|
6669
|
+
"required": true
|
|
6670
|
+
},
|
|
6671
|
+
"secretId": {
|
|
6672
|
+
"description": "Project secret ID (e.g. d2c4f48f-38e9-4b82-a36a-2b373fd14a65).",
|
|
6673
|
+
"name": "secretId",
|
|
6674
|
+
"required": true
|
|
6675
|
+
}
|
|
6676
|
+
},
|
|
6677
|
+
"description": "Detach a secret from a function without deleting the secret.",
|
|
6678
|
+
"examples": [
|
|
6679
|
+
"browse functions secrets detach <functionId> <secretId>",
|
|
6680
|
+
"browse functions secrets detach 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041 d2c4f48f-38e9-4b82-a36a-2b373fd14a65"
|
|
6681
|
+
],
|
|
6682
|
+
"flags": {
|
|
6683
|
+
"api-key": {
|
|
6684
|
+
"description": "Override the Browserbase API key.",
|
|
6685
|
+
"name": "api-key",
|
|
6686
|
+
"hasDynamicHelp": false,
|
|
6687
|
+
"helpValue": "<apiKey>",
|
|
6688
|
+
"multiple": false,
|
|
6689
|
+
"type": "option"
|
|
6690
|
+
},
|
|
6691
|
+
"base-url": {
|
|
6692
|
+
"description": "Override the Browserbase API base URL.",
|
|
6693
|
+
"name": "base-url",
|
|
6694
|
+
"hasDynamicHelp": false,
|
|
6695
|
+
"helpValue": "<baseUrl>",
|
|
6696
|
+
"multiple": false,
|
|
6697
|
+
"type": "option"
|
|
6698
|
+
}
|
|
6699
|
+
},
|
|
6700
|
+
"hasDynamicHelp": false,
|
|
6701
|
+
"hiddenAliases": [],
|
|
6702
|
+
"id": "functions:secrets:detach",
|
|
6703
|
+
"pluginAlias": "browse",
|
|
6704
|
+
"pluginName": "browse",
|
|
6705
|
+
"pluginType": "core",
|
|
6706
|
+
"strict": true,
|
|
6707
|
+
"isESM": true,
|
|
6708
|
+
"relativePath": [
|
|
6709
|
+
"dist",
|
|
6710
|
+
"commands",
|
|
6711
|
+
"functions",
|
|
6712
|
+
"secrets",
|
|
6713
|
+
"detach.js"
|
|
6714
|
+
]
|
|
6715
|
+
},
|
|
6716
|
+
"functions:secrets:list": {
|
|
6717
|
+
"aliases": [],
|
|
6718
|
+
"args": {
|
|
6719
|
+
"functionId": {
|
|
6720
|
+
"description": "Function ID (e.g. 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041).",
|
|
6721
|
+
"name": "functionId",
|
|
6722
|
+
"required": true
|
|
6723
|
+
}
|
|
6724
|
+
},
|
|
6725
|
+
"description": "List metadata for secrets attached to a function with cursor pagination.",
|
|
6726
|
+
"examples": [
|
|
6727
|
+
"browse functions secrets list <functionId>",
|
|
6728
|
+
"browse functions secrets list 7b6e1c42-8d93-4a15-b2f0-9c6d3e8a5041",
|
|
6729
|
+
"browse functions secrets list <functionId> --start-at 2026-01-01T00:00:00Z",
|
|
6730
|
+
"browse functions secrets list <functionId> --start-at 2026-01-01T00:00:00Z --end-at 2026-02-01T00:00:00Z",
|
|
6731
|
+
"browse functions secrets list <functionId> --limit 10"
|
|
6732
|
+
],
|
|
6733
|
+
"flags": {
|
|
6734
|
+
"api-key": {
|
|
6735
|
+
"description": "Override the Browserbase API key.",
|
|
6736
|
+
"name": "api-key",
|
|
6737
|
+
"hasDynamicHelp": false,
|
|
6738
|
+
"helpValue": "<apiKey>",
|
|
6739
|
+
"multiple": false,
|
|
6740
|
+
"type": "option"
|
|
6741
|
+
},
|
|
6742
|
+
"base-url": {
|
|
6743
|
+
"description": "Override the Browserbase API base URL.",
|
|
6744
|
+
"name": "base-url",
|
|
6745
|
+
"hasDynamicHelp": false,
|
|
6746
|
+
"helpValue": "<baseUrl>",
|
|
6747
|
+
"multiple": false,
|
|
6748
|
+
"type": "option"
|
|
6749
|
+
},
|
|
6750
|
+
"limit": {
|
|
6751
|
+
"description": "Maximum results per page (API default: 20).",
|
|
6752
|
+
"name": "limit",
|
|
6753
|
+
"hasDynamicHelp": false,
|
|
6754
|
+
"multiple": false,
|
|
6755
|
+
"type": "option"
|
|
6756
|
+
},
|
|
6757
|
+
"cursor": {
|
|
6758
|
+
"description": "nextCursor from the previous page. Keep the same filters.",
|
|
6759
|
+
"name": "cursor",
|
|
6760
|
+
"hasDynamicHelp": false,
|
|
6761
|
+
"multiple": false,
|
|
6762
|
+
"type": "option"
|
|
6763
|
+
},
|
|
6764
|
+
"start-at": {
|
|
6765
|
+
"description": "Include secrets created on or after this RFC 3339 timestamp.",
|
|
6766
|
+
"name": "start-at",
|
|
6767
|
+
"hasDynamicHelp": false,
|
|
6768
|
+
"multiple": false,
|
|
6769
|
+
"type": "option"
|
|
6770
|
+
},
|
|
6771
|
+
"end-at": {
|
|
6772
|
+
"description": "Include secrets created on or before this RFC 3339 timestamp.",
|
|
6773
|
+
"name": "end-at",
|
|
6774
|
+
"hasDynamicHelp": false,
|
|
6775
|
+
"multiple": false,
|
|
6776
|
+
"type": "option"
|
|
6777
|
+
}
|
|
6778
|
+
},
|
|
6779
|
+
"hasDynamicHelp": false,
|
|
6780
|
+
"hiddenAliases": [],
|
|
6781
|
+
"id": "functions:secrets:list",
|
|
6782
|
+
"pluginAlias": "browse",
|
|
6783
|
+
"pluginName": "browse",
|
|
6784
|
+
"pluginType": "core",
|
|
6785
|
+
"strict": true,
|
|
6786
|
+
"isESM": true,
|
|
6787
|
+
"relativePath": [
|
|
6788
|
+
"dist",
|
|
6789
|
+
"commands",
|
|
6790
|
+
"functions",
|
|
6791
|
+
"secrets",
|
|
6792
|
+
"list.js"
|
|
6793
|
+
]
|
|
6794
|
+
},
|
|
6303
6795
|
"cloud:sessions:downloads:get": {
|
|
6304
6796
|
"aliases": [],
|
|
6305
6797
|
"args": {
|
|
@@ -6411,5 +6903,5 @@
|
|
|
6411
6903
|
]
|
|
6412
6904
|
}
|
|
6413
6905
|
},
|
|
6414
|
-
"version": "0.
|
|
6906
|
+
"version": "0.11.0"
|
|
6415
6907
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Unified Browserbase CLI for browser automation and cloud APIs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
"cloud": {
|
|
37
37
|
"description": "Manage Browserbase cloud resources and APIs."
|
|
38
38
|
},
|
|
39
|
+
"cloud:secrets": {
|
|
40
|
+
"description": "Create, list, retrieve, update, and delete project secrets."
|
|
41
|
+
},
|
|
39
42
|
"cloud:projects": {
|
|
40
43
|
"description": "Manage Browserbase projects."
|
|
41
44
|
},
|
|
@@ -54,6 +57,9 @@
|
|
|
54
57
|
"cloud:sessions:uploads": {
|
|
55
58
|
"description": "Upload files to Browserbase sessions."
|
|
56
59
|
},
|
|
60
|
+
"functions:secrets": {
|
|
61
|
+
"description": "List, attach, and detach project secrets for functions."
|
|
62
|
+
},
|
|
57
63
|
"functions": {
|
|
58
64
|
"description": "Develop, publish, and invoke Browserbase Functions."
|
|
59
65
|
},
|
|
@@ -88,6 +94,9 @@
|
|
|
88
94
|
},
|
|
89
95
|
"dependencies": {
|
|
90
96
|
"@browserbasehq/sdk": "^2.14.0",
|
|
97
|
+
"@hpke/core": "^1.9.0",
|
|
98
|
+
"@hpke/dhkem-x25519": "^1.8.0",
|
|
99
|
+
"@inquirer/password": "^4.0.23",
|
|
91
100
|
"@oclif/core": "^4.11.0",
|
|
92
101
|
"@vercel/detect-agent": "^1.2.3",
|
|
93
102
|
"archiver": "^7.0.1",
|