braaand 0.1.0 → 0.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.
- package/README.md +97 -15
- package/dist/api.d.ts +27 -1
- package/dist/api.js +116 -11
- package/dist/api.js.map +1 -1
- package/dist/commands/assets.d.ts +5 -0
- package/dist/commands/assets.js +42 -29
- package/dist/commands/assets.js.map +1 -1
- package/dist/commands/brands.d.ts +8 -0
- package/dist/commands/brands.js +37 -0
- package/dist/commands/brands.js.map +1 -1
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +17 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/projects.d.ts +21 -0
- package/dist/commands/projects.js +101 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/render.d.ts +11 -2
- package/dist/commands/render.js +94 -37
- package/dist/commands/render.js.map +1 -1
- package/dist/commands/templates.d.ts +7 -0
- package/dist/commands/templates.js +48 -3
- package/dist/commands/templates.js.map +1 -1
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.js +21 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +8 -2
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +26 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +149 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# braaand
|
|
2
2
|
|
|
3
|
-
CLI for [Braaand](https://braaand.ai) — brand infrastructure for agentic automation.
|
|
3
|
+
CLI for [Braaand](https://www.braaand.ai) — brand infrastructure for agentic automation.
|
|
4
4
|
|
|
5
|
-
Manage brands, assets, templates, and renders from the terminal. AI agents use the same tool via Claude Code skills.
|
|
5
|
+
Manage brands, assets, templates, projects, ad sets, and renders from the terminal. AI agents use the same tool via Claude Code skills.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -13,25 +13,107 @@ npm install -g braaand
|
|
|
13
13
|
## Auth
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
braaand auth login # Device auth flow
|
|
17
|
-
braaand
|
|
16
|
+
braaand auth login # Device auth flow (opens browser)
|
|
17
|
+
braaand whoami # Who you're authed as + brand counts
|
|
18
|
+
braaand auth logout # Remove stored credentials
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
## Commands
|
|
21
22
|
|
|
23
|
+
### Brands
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
braaand brands list
|
|
27
|
+
braaand brands get <id>
|
|
28
|
+
braaand brands config <id> # colors, fonts, voice, tokens
|
|
29
|
+
braaand brands info <id> # Full dump with asset URLs
|
|
30
|
+
braaand brands knowledge <id> [sectionId]
|
|
31
|
+
braaand brands portal <id> # Open brand portal in browser
|
|
32
|
+
braaand brands create <name> [--description <d>]
|
|
33
|
+
braaand brands update <id> [--name <n>] [--description <d>]
|
|
34
|
+
braaand brands delete <id> --yes --confirm-brand-id <id>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Assets
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
braaand assets list <brandId>
|
|
41
|
+
braaand assets get <brandId> <assetId> [--meta] [--output <path>]
|
|
42
|
+
braaand assets upload <brandId> <file> [--name <n>] [--type logo|image|font|icon|symbol|document]
|
|
43
|
+
braaand assets delete <brandId> <assetId>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Templates
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
braaand templates list <brandId>
|
|
50
|
+
braaand templates get <brandId> <templateId>
|
|
51
|
+
braaand templates discover <brandId> # Agent-facing catalog
|
|
52
|
+
braaand templates create <brandId> <name> [--from <file.json>]
|
|
53
|
+
braaand templates delete <brandId> <templateId> [--force]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### System templates
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
braaand system-templates list
|
|
60
|
+
braaand system-templates instantiate <id> --brand <brandId>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Projects & ad sets
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
braaand projects list <brandId>
|
|
67
|
+
braaand projects create <brandId> <name> [--description <d>]
|
|
68
|
+
braaand projects update <brandId> <projectId> [--name <n>]
|
|
69
|
+
braaand projects delete <brandId> <projectId>
|
|
70
|
+
|
|
71
|
+
braaand adsets list <brandId> <projectId>
|
|
72
|
+
braaand adsets create <brandId> <projectId> <name> --ads @ads.json
|
|
73
|
+
braaand adsets update <brandId> <projectId> <adSetId> --ads @ads.json
|
|
74
|
+
braaand adsets delete <brandId> <projectId> <adSetId>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Rendering
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Single format
|
|
81
|
+
braaand render <brandId> <templateId> --format 1x1 --output hero.png
|
|
82
|
+
|
|
83
|
+
# Multiple formats (comma-separated)
|
|
84
|
+
braaand render <brandId> <templateId> --format 1x1,9x16,4x5 --output hero
|
|
85
|
+
# → writes hero-1x1.png, hero-9x16.png, hero-4x5.png
|
|
86
|
+
|
|
87
|
+
# All formats the template supports
|
|
88
|
+
braaand render <brandId> <templateId> --all-formats --output hero
|
|
89
|
+
|
|
90
|
+
# Batch render a saved ad set
|
|
91
|
+
braaand render batch <brandId> <projectId> <adSetId> --output-dir ./renders
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Onboarding & sync
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
braaand onboard <file.json> # Create brand + config + assets
|
|
98
|
+
braaand sync [brandId] [--dir <path>] # Sync brand assets locally
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Config
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
braaand config show # Current API URL + auth state
|
|
105
|
+
braaand config set-url <url> # Default: https://www.braaand.ai
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Output
|
|
109
|
+
|
|
110
|
+
All commands output JSON to stdout. Pipe to `jq` for filtering:
|
|
111
|
+
|
|
22
112
|
```bash
|
|
23
|
-
braaand brands list
|
|
24
|
-
braaand
|
|
25
|
-
braaand brands info <brandId> # Full dump with asset URLs
|
|
26
|
-
braaand assets list <brandId> # List assets
|
|
27
|
-
braaand assets upload <brandId> <file> # Upload asset
|
|
28
|
-
braaand templates discover <brandId> # Agent-facing catalog
|
|
29
|
-
braaand system-templates list # Browse system templates
|
|
30
|
-
braaand render <brandId> <templateId> # Render to PNG
|
|
31
|
-
braaand onboard <file.json> # Create brand + config + assets
|
|
32
|
-
braaand sync # Sync brand assets locally
|
|
113
|
+
braaand brands list | jq '.[].name'
|
|
114
|
+
braaand assets list my-brand | jq '.[] | select(.type == "font") | .name'
|
|
33
115
|
```
|
|
34
116
|
|
|
35
117
|
## More
|
|
36
118
|
|
|
37
|
-
See [braaand.ai](https://braaand.ai) for full documentation.
|
|
119
|
+
See [braaand.ai](https://www.braaand.ai) for full documentation.
|
package/dist/api.d.ts
CHANGED
|
@@ -2,8 +2,34 @@ export declare class ApiError extends Error {
|
|
|
2
2
|
status: number;
|
|
3
3
|
constructor(status: number, message: string);
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Read the API key or throw ApiError(401).
|
|
7
|
+
* Use this in commands that need auth — replaces duplicated checks.
|
|
8
|
+
*/
|
|
9
|
+
export declare function requireAuth(): string;
|
|
10
|
+
interface FetchOptions extends Omit<RequestInit, "body"> {
|
|
11
|
+
body?: BodyInit | Record<string, unknown> | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* JSON API fetch with auth.
|
|
15
|
+
* Auto-stringifies plain object bodies. For multipart uploads use apiUpload.
|
|
16
|
+
*/
|
|
17
|
+
export declare function apiFetch(path: string, options?: FetchOptions): Promise<unknown>;
|
|
18
|
+
/**
|
|
19
|
+
* Multipart upload with auth. Sets Authorization but lets fetch set the
|
|
20
|
+
* multipart boundary via Content-Type.
|
|
21
|
+
*/
|
|
22
|
+
export declare function apiUpload(path: string, form: FormData): Promise<unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Binary download with auth. Returns buffer and response headers
|
|
25
|
+
* (so callers can read custom headers like x-render-id).
|
|
26
|
+
*/
|
|
27
|
+
export declare function apiDownload(path: string, options?: FetchOptions): Promise<{
|
|
28
|
+
buffer: Buffer;
|
|
29
|
+
headers: Headers;
|
|
30
|
+
}>;
|
|
6
31
|
/**
|
|
7
32
|
* Unauthenticated fetch for public endpoints (device auth).
|
|
8
33
|
*/
|
|
9
34
|
export declare function publicFetch(url: string, options?: RequestInit): Promise<unknown>;
|
|
35
|
+
export {};
|
package/dist/api.js
CHANGED
|
@@ -6,15 +6,40 @@ export class ApiError extends Error {
|
|
|
6
6
|
this.status = status;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Read the API key or throw ApiError(401).
|
|
11
|
+
* Use this in commands that need auth — replaces duplicated checks.
|
|
12
|
+
*/
|
|
13
|
+
export function requireAuth() {
|
|
14
|
+
const key = getApiKey();
|
|
15
|
+
if (!key) {
|
|
16
|
+
throw new ApiError(401, "Not authenticated. Run: braaand auth login");
|
|
17
|
+
}
|
|
18
|
+
return key;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* JSON API fetch with auth.
|
|
22
|
+
* Auto-stringifies plain object bodies. For multipart uploads use apiUpload.
|
|
23
|
+
*/
|
|
9
24
|
export async function apiFetch(path, options = {}) {
|
|
25
|
+
const apiKey = requireAuth();
|
|
10
26
|
const config = getConfig();
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
|
|
27
|
+
let body = undefined;
|
|
28
|
+
if (options.body != null) {
|
|
29
|
+
if (typeof options.body === "object" &&
|
|
30
|
+
!(options.body instanceof FormData) &&
|
|
31
|
+
!(options.body instanceof ArrayBuffer) &&
|
|
32
|
+
!(options.body instanceof Uint8Array) &&
|
|
33
|
+
!(options.body instanceof Blob)) {
|
|
34
|
+
body = JSON.stringify(options.body);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
body = options.body;
|
|
38
|
+
}
|
|
14
39
|
}
|
|
15
|
-
const
|
|
16
|
-
const res = await fetch(url, {
|
|
40
|
+
const res = await fetch(`${config.apiUrl}${path}`, {
|
|
17
41
|
...options,
|
|
42
|
+
body,
|
|
18
43
|
headers: {
|
|
19
44
|
"Authorization": `Bearer ${apiKey}`,
|
|
20
45
|
"Content-Type": "application/json",
|
|
@@ -22,22 +47,101 @@ export async function apiFetch(path, options = {}) {
|
|
|
22
47
|
},
|
|
23
48
|
});
|
|
24
49
|
if (!res.ok) {
|
|
25
|
-
const
|
|
50
|
+
const text = await res.text();
|
|
26
51
|
let message;
|
|
27
52
|
try {
|
|
28
|
-
const json = JSON.parse(
|
|
29
|
-
message = json.error || json.message ||
|
|
53
|
+
const json = JSON.parse(text);
|
|
54
|
+
message = json.error || json.message || text;
|
|
30
55
|
}
|
|
31
56
|
catch {
|
|
32
|
-
message =
|
|
57
|
+
message = text;
|
|
33
58
|
}
|
|
34
59
|
throw new ApiError(res.status, `${res.status} ${message}`);
|
|
35
60
|
}
|
|
61
|
+
// DELETE may return empty body
|
|
62
|
+
const text = await res.text();
|
|
63
|
+
if (!text)
|
|
64
|
+
return {};
|
|
36
65
|
const contentType = res.headers.get("content-type") ?? "";
|
|
37
66
|
if (contentType.includes("application/json")) {
|
|
38
|
-
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(text);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return text;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return text;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Multipart upload with auth. Sets Authorization but lets fetch set the
|
|
78
|
+
* multipart boundary via Content-Type.
|
|
79
|
+
*/
|
|
80
|
+
export async function apiUpload(path, form) {
|
|
81
|
+
const apiKey = requireAuth();
|
|
82
|
+
const config = getConfig();
|
|
83
|
+
const res = await fetch(`${config.apiUrl}${path}`, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: { "Authorization": `Bearer ${apiKey}` },
|
|
86
|
+
body: form,
|
|
87
|
+
});
|
|
88
|
+
if (!res.ok) {
|
|
89
|
+
const text = await res.text();
|
|
90
|
+
let message;
|
|
91
|
+
try {
|
|
92
|
+
const json = JSON.parse(text);
|
|
93
|
+
message = json.error || json.message || text;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
message = text;
|
|
97
|
+
}
|
|
98
|
+
throw new ApiError(res.status, `${res.status} ${message}`);
|
|
99
|
+
}
|
|
100
|
+
return res.json();
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Binary download with auth. Returns buffer and response headers
|
|
104
|
+
* (so callers can read custom headers like x-render-id).
|
|
105
|
+
*/
|
|
106
|
+
export async function apiDownload(path, options = {}) {
|
|
107
|
+
const apiKey = requireAuth();
|
|
108
|
+
const config = getConfig();
|
|
109
|
+
let body = undefined;
|
|
110
|
+
if (options.body != null) {
|
|
111
|
+
if (typeof options.body === "object" &&
|
|
112
|
+
!(options.body instanceof FormData) &&
|
|
113
|
+
!(options.body instanceof ArrayBuffer) &&
|
|
114
|
+
!(options.body instanceof Uint8Array) &&
|
|
115
|
+
!(options.body instanceof Blob)) {
|
|
116
|
+
body = JSON.stringify(options.body);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
body = options.body;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const res = await fetch(`${config.apiUrl}${path}`, {
|
|
123
|
+
...options,
|
|
124
|
+
body,
|
|
125
|
+
headers: {
|
|
126
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
127
|
+
"Content-Type": "application/json",
|
|
128
|
+
...options.headers,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
if (!res.ok) {
|
|
132
|
+
const text = await res.text();
|
|
133
|
+
let message;
|
|
134
|
+
try {
|
|
135
|
+
const json = JSON.parse(text);
|
|
136
|
+
message = json.error || json.message || text;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
message = text;
|
|
140
|
+
}
|
|
141
|
+
throw new ApiError(res.status, `${res.status} ${message}`);
|
|
39
142
|
}
|
|
40
|
-
|
|
143
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
144
|
+
return { buffer, headers: res.headers };
|
|
41
145
|
}
|
|
42
146
|
/**
|
|
43
147
|
* Unauthenticated fetch for public endpoints (device auth).
|
|
@@ -45,6 +149,7 @@ export async function apiFetch(path, options = {}) {
|
|
|
45
149
|
export async function publicFetch(url, options = {}) {
|
|
46
150
|
const res = await fetch(url, {
|
|
47
151
|
...options,
|
|
152
|
+
redirect: "follow",
|
|
48
153
|
headers: {
|
|
49
154
|
"Content-Type": "application/json",
|
|
50
155
|
...options.headers,
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,OAAO,QAAS,SAAQ,KAAK;IACd;IAAnB,YAAmB,MAAc,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,WAAM,GAAN,MAAM,CAAQ;IAEjC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export declare function list(brandId: string): Promise<void>;
|
|
2
|
+
export declare function get(brandId: string, assetId: string, options: {
|
|
3
|
+
meta?: boolean;
|
|
4
|
+
output?: string;
|
|
5
|
+
}): Promise<void>;
|
|
2
6
|
export declare function upload(brandId: string, filePath: string, options: {
|
|
3
7
|
name?: string;
|
|
4
8
|
type?: string;
|
|
5
9
|
tags?: string;
|
|
6
10
|
description?: string;
|
|
7
11
|
}): Promise<void>;
|
|
12
|
+
export declare function remove(brandId: string, assetId: string): Promise<void>;
|
package/dist/commands/assets.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { basename, extname } from "path";
|
|
3
|
-
import {
|
|
4
|
-
import { apiFetch } from "../api.js";
|
|
3
|
+
import { getConfig } from "../config.js";
|
|
4
|
+
import { apiFetch, apiUpload, apiDownload } from "../api.js";
|
|
5
|
+
import { exitWithUsage } from "../errors.js";
|
|
5
6
|
const MIME_MAP = {
|
|
6
7
|
".svg": "image/svg+xml",
|
|
7
8
|
".png": "image/png",
|
|
@@ -20,10 +21,8 @@ function getMime(filename) {
|
|
|
20
21
|
return MIME_MAP[ext] || "application/octet-stream";
|
|
21
22
|
}
|
|
22
23
|
export async function list(brandId) {
|
|
23
|
-
if (!brandId)
|
|
24
|
-
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
24
|
+
if (!brandId)
|
|
25
|
+
exitWithUsage("Usage: braaand assets list <brandId>");
|
|
27
26
|
const apiUrl = getConfig().apiUrl;
|
|
28
27
|
const assets = (await apiFetch(`/api/brands/${brandId}/assets`));
|
|
29
28
|
const enriched = assets.map((a) => ({
|
|
@@ -32,49 +31,63 @@ export async function list(brandId) {
|
|
|
32
31
|
}));
|
|
33
32
|
console.log(JSON.stringify(enriched, null, 2));
|
|
34
33
|
}
|
|
34
|
+
export async function get(brandId, assetId, options) {
|
|
35
|
+
if (!brandId || !assetId) {
|
|
36
|
+
exitWithUsage("Usage: braaand assets get <brandId> <assetId> [--meta] [--output <path>]");
|
|
37
|
+
}
|
|
38
|
+
if (options.meta) {
|
|
39
|
+
const meta = await apiFetch(`/api/brands/${brandId}/assets/${assetId}?meta`);
|
|
40
|
+
console.log(JSON.stringify(meta, null, 2));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Download binary
|
|
44
|
+
const { buffer, headers } = await apiDownload(`/api/brands/${brandId}/assets/${assetId}`);
|
|
45
|
+
const contentType = headers.get("content-type") ?? "application/octet-stream";
|
|
46
|
+
// Infer extension from content-type
|
|
47
|
+
const ext = (() => {
|
|
48
|
+
for (const [e, mt] of Object.entries(MIME_MAP)) {
|
|
49
|
+
if (mt === contentType)
|
|
50
|
+
return e;
|
|
51
|
+
}
|
|
52
|
+
return ".bin";
|
|
53
|
+
})();
|
|
54
|
+
const filename = options.output ?? `${assetId}${ext}`;
|
|
55
|
+
writeFileSync(filename, buffer);
|
|
56
|
+
console.log(`Downloaded to ${filename} (${buffer.length} bytes, ${contentType})`);
|
|
57
|
+
}
|
|
35
58
|
export async function upload(brandId, filePath, options) {
|
|
36
59
|
if (!brandId || !filePath) {
|
|
37
|
-
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
const config = getConfig();
|
|
41
|
-
const apiKey = getApiKey();
|
|
42
|
-
if (!apiKey) {
|
|
43
|
-
console.error("Not authenticated. Run: braaand auth login");
|
|
44
|
-
process.exit(1);
|
|
60
|
+
exitWithUsage("Usage: braaand assets upload <brandId> <file> [--name <name>] [--type logo|image|font|icon|symbol|document] [--tags <comma-sep>] [--description <desc>]");
|
|
45
61
|
}
|
|
46
62
|
const buffer = readFileSync(filePath);
|
|
47
63
|
const filename = basename(filePath);
|
|
48
64
|
const mime = getMime(filename);
|
|
49
|
-
// Infer asset type from file extension if not specified
|
|
50
65
|
const inferredType = options.type || (() => {
|
|
51
66
|
const ext = extname(filename).toLowerCase();
|
|
52
67
|
if ([".woff", ".woff2", ".ttf", ".otf"].includes(ext))
|
|
53
68
|
return "font";
|
|
54
69
|
if (ext === ".svg")
|
|
55
70
|
return "logo";
|
|
71
|
+
if (ext === ".pdf")
|
|
72
|
+
return "document";
|
|
56
73
|
return "image";
|
|
57
74
|
})();
|
|
58
|
-
// Build multipart form data
|
|
59
75
|
const form = new FormData();
|
|
60
|
-
form.append("file", new Blob([buffer], { type: mime }), filename);
|
|
76
|
+
form.append("file", new Blob([new Uint8Array(buffer)], { type: mime }), filename);
|
|
61
77
|
form.append("name", options.name || filename.replace(/\.[^.]+$/, ""));
|
|
62
78
|
form.append("type", inferredType);
|
|
63
79
|
if (options.tags)
|
|
64
80
|
form.append("tags", options.tags);
|
|
65
81
|
if (options.description)
|
|
66
82
|
form.append("description", options.description);
|
|
67
|
-
const
|
|
68
|
-
method: "POST",
|
|
69
|
-
headers: { "Authorization": `Bearer ${apiKey}` },
|
|
70
|
-
body: form,
|
|
71
|
-
});
|
|
72
|
-
if (!res.ok) {
|
|
73
|
-
const text = await res.text();
|
|
74
|
-
console.error(`Upload failed: ${res.status} ${text}`);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
const asset = await res.json();
|
|
83
|
+
const asset = await apiUpload(`/api/brands/${brandId}/assets`, form);
|
|
78
84
|
console.log(JSON.stringify(asset, null, 2));
|
|
79
85
|
}
|
|
86
|
+
export async function remove(brandId, assetId) {
|
|
87
|
+
if (!brandId || !assetId) {
|
|
88
|
+
exitWithUsage("Usage: braaand assets delete <brandId> <assetId>");
|
|
89
|
+
}
|
|
90
|
+
await apiFetch(`/api/brands/${brandId}/assets/${assetId}`, { method: "DELETE" });
|
|
91
|
+
console.log(JSON.stringify({ deleted: assetId }, null, 2));
|
|
92
|
+
}
|
|
80
93
|
//# sourceMappingURL=assets.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/commands/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/commands/assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,4 +4,12 @@ export declare function get(brandId: string): Promise<void>;
|
|
|
4
4
|
export declare function config(brandId: string): Promise<void>;
|
|
5
5
|
export declare function info(brandId: string): Promise<void>;
|
|
6
6
|
export declare function knowledge(brandId: string, sectionId?: string): Promise<void>;
|
|
7
|
+
export declare function update(brandId: string, patch: {
|
|
8
|
+
name?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function remove(brandId: string, options: {
|
|
12
|
+
yes?: boolean;
|
|
13
|
+
confirmBrandId?: string;
|
|
14
|
+
}): Promise<void>;
|
|
7
15
|
export declare function portal(brandId: string): Promise<void>;
|
package/dist/commands/brands.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { apiFetch } from "../api.js";
|
|
2
2
|
import { getConfig } from "../config.js";
|
|
3
|
+
import { exitWithUsage } from "../errors.js";
|
|
3
4
|
export async function list() {
|
|
4
5
|
const brands = await apiFetch("/api/brands");
|
|
5
6
|
console.log(JSON.stringify(brands, null, 2));
|
|
@@ -68,6 +69,42 @@ export async function knowledge(brandId, sectionId) {
|
|
|
68
69
|
console.log(JSON.stringify(sections, null, 2));
|
|
69
70
|
}
|
|
70
71
|
}
|
|
72
|
+
export async function update(brandId, patch) {
|
|
73
|
+
if (!brandId) {
|
|
74
|
+
exitWithUsage("Usage: braaand brands update <brandId> [--name <n>] [--description <d>]");
|
|
75
|
+
}
|
|
76
|
+
const body = {};
|
|
77
|
+
if (patch.name !== undefined)
|
|
78
|
+
body.name = patch.name;
|
|
79
|
+
if (patch.description !== undefined)
|
|
80
|
+
body.description = patch.description;
|
|
81
|
+
const brand = await apiFetch(`/api/brands/${brandId}`, {
|
|
82
|
+
method: "PUT",
|
|
83
|
+
body,
|
|
84
|
+
});
|
|
85
|
+
console.log(JSON.stringify(brand, null, 2));
|
|
86
|
+
}
|
|
87
|
+
export async function remove(brandId, options) {
|
|
88
|
+
if (!brandId) {
|
|
89
|
+
exitWithUsage("Usage: braaand brands delete <brandId> --yes --confirm-brand-id <brandId>");
|
|
90
|
+
}
|
|
91
|
+
if (!options.yes) {
|
|
92
|
+
exitWithUsage("Refusing to delete: pass --yes to confirm. Brand deletion is owner-only and permanently removes all projects, ad sets, templates, and assets.");
|
|
93
|
+
}
|
|
94
|
+
if (options.confirmBrandId !== brandId) {
|
|
95
|
+
exitWithUsage(`Refusing to delete: --confirm-brand-id must match <brandId> exactly. Got "${options.confirmBrandId ?? ""}".`);
|
|
96
|
+
}
|
|
97
|
+
// Best-effort: show what's about to be deleted
|
|
98
|
+
try {
|
|
99
|
+
const info = (await apiFetch(`/api/brands/${brandId}`));
|
|
100
|
+
console.error(`Deleting brand: ${info.name ?? brandId}`);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// ignore — we still attempt delete
|
|
104
|
+
}
|
|
105
|
+
await apiFetch(`/api/brands/${brandId}`, { method: "DELETE" });
|
|
106
|
+
console.log(JSON.stringify({ deleted: brandId }, null, 2));
|
|
107
|
+
}
|
|
71
108
|
export async function portal(brandId) {
|
|
72
109
|
if (!brandId) {
|
|
73
110
|
console.error("Usage: braaand brands portal <brandId>");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../../src/commands/brands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../../src/commands/brands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getConfig, getCredentials, getCredentialsPath, saveConfig } from "../config.js";
|
|
2
|
+
export function show() {
|
|
3
|
+
const config = getConfig();
|
|
4
|
+
const creds = getCredentials();
|
|
5
|
+
const out = {
|
|
6
|
+
apiUrl: config.apiUrl,
|
|
7
|
+
authenticated: !!creds?.apiKey,
|
|
8
|
+
apiKeyPrefix: creds?.apiKey ? `${creds.apiKey.slice(0, 11)}…` : null,
|
|
9
|
+
credentialsPath: getCredentialsPath(),
|
|
10
|
+
};
|
|
11
|
+
console.log(JSON.stringify(out, null, 2));
|
|
12
|
+
}
|
|
13
|
+
export function setUrl(url) {
|
|
14
|
+
saveConfig({ apiUrl: url });
|
|
15
|
+
console.log(`API URL set to ${url}`);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzF,MAAM,UAAU,IAAI;IAClB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG;QACV,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM;QAC9B,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;QACpE,eAAe,EAAE,kBAAkB,EAAE;KACtC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare function list(brandId: string): Promise<void>;
|
|
2
|
+
export declare function get(brandId: string, projectId: string): Promise<void>;
|
|
3
|
+
export declare function create(brandId: string, name: string, description?: string, externalId?: string): Promise<void>;
|
|
4
|
+
export declare function update(brandId: string, projectId: string, patch: {
|
|
5
|
+
name?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
externalId?: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
export declare function remove(brandId: string, projectId: string): Promise<void>;
|
|
10
|
+
export declare function adsetsList(brandId: string, projectId: string): Promise<void>;
|
|
11
|
+
export declare function adsetsGet(brandId: string, projectId: string, adSetId: string): Promise<void>;
|
|
12
|
+
export declare function adsetsCreate(brandId: string, projectId: string, name: string, opts: {
|
|
13
|
+
description?: string;
|
|
14
|
+
ads?: string;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export declare function adsetsUpdate(brandId: string, projectId: string, adSetId: string, patch: {
|
|
17
|
+
name?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
ads?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export declare function adsetsRemove(brandId: string, projectId: string, adSetId: string): Promise<void>;
|