braaand 0.1.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 ADDED
@@ -0,0 +1,37 @@
1
+ # braaand
2
+
3
+ CLI for [Braaand](https://braaand.ai) — brand infrastructure for agentic automation.
4
+
5
+ Manage brands, assets, templates, and renders from the terminal. AI agents use the same tool via Claude Code skills.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g braaand
11
+ ```
12
+
13
+ ## Auth
14
+
15
+ ```bash
16
+ braaand auth login # Device auth flow
17
+ braaand auth status # Check connection
18
+ ```
19
+
20
+ ## Commands
21
+
22
+ ```bash
23
+ braaand brands list # List brands
24
+ braaand brands config <brandId> # Get brand config
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
33
+ ```
34
+
35
+ ## More
36
+
37
+ See [braaand.ai](https://braaand.ai) for full documentation.
package/dist/api.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare class ApiError extends Error {
2
+ status: number;
3
+ constructor(status: number, message: string);
4
+ }
5
+ export declare function apiFetch(path: string, options?: RequestInit): Promise<unknown>;
6
+ /**
7
+ * Unauthenticated fetch for public endpoints (device auth).
8
+ */
9
+ export declare function publicFetch(url: string, options?: RequestInit): Promise<unknown>;
package/dist/api.js ADDED
@@ -0,0 +1,61 @@
1
+ import { getApiKey, getConfig } from "./config.js";
2
+ export class ApiError extends Error {
3
+ status;
4
+ constructor(status, message) {
5
+ super(message);
6
+ this.status = status;
7
+ }
8
+ }
9
+ export async function apiFetch(path, options = {}) {
10
+ const config = getConfig();
11
+ const apiKey = getApiKey();
12
+ if (!apiKey) {
13
+ throw new ApiError(401, "Not authenticated. Run: braaand auth login");
14
+ }
15
+ const url = `${config.apiUrl}${path}`;
16
+ const res = await fetch(url, {
17
+ ...options,
18
+ headers: {
19
+ "Authorization": `Bearer ${apiKey}`,
20
+ "Content-Type": "application/json",
21
+ ...options.headers,
22
+ },
23
+ });
24
+ if (!res.ok) {
25
+ const body = await res.text();
26
+ let message;
27
+ try {
28
+ const json = JSON.parse(body);
29
+ message = json.error || json.message || body;
30
+ }
31
+ catch {
32
+ message = body;
33
+ }
34
+ throw new ApiError(res.status, `${res.status} ${message}`);
35
+ }
36
+ const contentType = res.headers.get("content-type") ?? "";
37
+ if (contentType.includes("application/json")) {
38
+ return res.json();
39
+ }
40
+ return res.text();
41
+ }
42
+ /**
43
+ * Unauthenticated fetch for public endpoints (device auth).
44
+ */
45
+ export async function publicFetch(url, options = {}) {
46
+ const res = await fetch(url, {
47
+ ...options,
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ ...options.headers,
51
+ },
52
+ });
53
+ const body = await res.text();
54
+ try {
55
+ return JSON.parse(body);
56
+ }
57
+ catch {
58
+ return body;
59
+ }
60
+ }
61
+ //# sourceMappingURL=api.js.map
@@ -0,0 +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,CAC5B,IAAY,EACZ,UAAuB,EAAE;IAEzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,4CAA4C,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE;YACP,eAAe,EAAE,UAAU,MAAM,EAAE;YACnC,cAAc,EAAE,kBAAkB;YAClC,GAAG,OAAO,CAAC,OAAO;SACnB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAW,EACX,UAAuB,EAAE;IAEzB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,GAAG,OAAO,CAAC,OAAO;SACnB;KACF,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function list(brandId: string): Promise<void>;
2
+ export declare function upload(brandId: string, filePath: string, options: {
3
+ name?: string;
4
+ type?: string;
5
+ tags?: string;
6
+ description?: string;
7
+ }): Promise<void>;
@@ -0,0 +1,80 @@
1
+ import { readFileSync } from "fs";
2
+ import { basename, extname } from "path";
3
+ import { getApiKey, getConfig } from "../config.js";
4
+ import { apiFetch } from "../api.js";
5
+ const MIME_MAP = {
6
+ ".svg": "image/svg+xml",
7
+ ".png": "image/png",
8
+ ".jpg": "image/jpeg",
9
+ ".jpeg": "image/jpeg",
10
+ ".webp": "image/webp",
11
+ ".gif": "image/gif",
12
+ ".woff": "font/woff",
13
+ ".woff2": "font/woff2",
14
+ ".ttf": "font/ttf",
15
+ ".otf": "font/otf",
16
+ ".pdf": "application/pdf",
17
+ };
18
+ function getMime(filename) {
19
+ const ext = extname(filename).toLowerCase();
20
+ return MIME_MAP[ext] || "application/octet-stream";
21
+ }
22
+ export async function list(brandId) {
23
+ if (!brandId) {
24
+ console.error("Usage: braaand assets list <brandId>");
25
+ process.exit(1);
26
+ }
27
+ const apiUrl = getConfig().apiUrl;
28
+ const assets = (await apiFetch(`/api/brands/${brandId}/assets`));
29
+ const enriched = assets.map((a) => ({
30
+ ...a,
31
+ url: `${apiUrl}/api/brands/${brandId}/assets/${a.id}`,
32
+ }));
33
+ console.log(JSON.stringify(enriched, null, 2));
34
+ }
35
+ export async function upload(brandId, filePath, options) {
36
+ if (!brandId || !filePath) {
37
+ console.error("Usage: braaand assets upload <brandId> <file> [--name <name>] [--type logo|image|font|icon|symbol] [--tags <comma-sep>] [--description <desc>]");
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);
45
+ }
46
+ const buffer = readFileSync(filePath);
47
+ const filename = basename(filePath);
48
+ const mime = getMime(filename);
49
+ // Infer asset type from file extension if not specified
50
+ const inferredType = options.type || (() => {
51
+ const ext = extname(filename).toLowerCase();
52
+ if ([".woff", ".woff2", ".ttf", ".otf"].includes(ext))
53
+ return "font";
54
+ if (ext === ".svg")
55
+ return "logo";
56
+ return "image";
57
+ })();
58
+ // Build multipart form data
59
+ const form = new FormData();
60
+ form.append("file", new Blob([buffer], { type: mime }), filename);
61
+ form.append("name", options.name || filename.replace(/\.[^.]+$/, ""));
62
+ form.append("type", inferredType);
63
+ if (options.tags)
64
+ form.append("tags", options.tags);
65
+ if (options.description)
66
+ form.append("description", options.description);
67
+ const res = await fetch(`${config.apiUrl}/api/brands/${brandId}/assets`, {
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();
78
+ console.log(JSON.stringify(asset, null, 2));
79
+ }
80
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/commands/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function login(): Promise<void>;
2
+ export declare function logout(): Promise<void>;
3
+ export declare function status(): Promise<void>;
@@ -0,0 +1,66 @@
1
+ import { publicFetch, apiFetch } from "../api.js";
2
+ import { saveCredentials, deleteCredentials, getCredentials, getConfig } from "../config.js";
3
+ export async function login() {
4
+ const config = getConfig();
5
+ const codeUrl = `${config.apiUrl}/api/auth/device/code`;
6
+ console.log("Starting device authorization...\n");
7
+ const data = (await publicFetch(codeUrl, { method: "POST" }));
8
+ console.log(` Open this URL in your browser:`);
9
+ console.log(` ${data.verification_uri}\n`);
10
+ console.log(` Enter code: ${data.user_code}\n`);
11
+ // Try to open browser automatically
12
+ try {
13
+ const { exec } = await import("child_process");
14
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
15
+ exec(`${cmd} "${data.verification_uri}"`);
16
+ console.log(" (Browser opened automatically)\n");
17
+ }
18
+ catch {
19
+ // Silently fail — user can open manually
20
+ }
21
+ // Poll for token
22
+ console.log("Waiting for authorization...");
23
+ const tokenUrl = `${config.apiUrl}/api/auth/device/token`;
24
+ const deadline = Date.now() + data.expires_in * 1000;
25
+ while (Date.now() < deadline) {
26
+ await new Promise((r) => setTimeout(r, data.interval * 1000));
27
+ const result = (await publicFetch(tokenUrl, {
28
+ method: "POST",
29
+ body: JSON.stringify({ device_code: data.device_code }),
30
+ }));
31
+ if (result.access_token) {
32
+ saveCredentials({ apiKey: result.access_token });
33
+ console.log("\nAuthenticated successfully!");
34
+ console.log(`API key saved to ~/.braaand/credentials.json`);
35
+ return;
36
+ }
37
+ if (result.error && result.error !== "authorization_pending") {
38
+ console.error(`\nAuthorization failed: ${result.error}`);
39
+ process.exit(1);
40
+ }
41
+ process.stdout.write(".");
42
+ }
43
+ console.error("\nAuthorization timed out. Please try again.");
44
+ process.exit(1);
45
+ }
46
+ export async function logout() {
47
+ deleteCredentials();
48
+ console.log("Logged out. Credentials removed.");
49
+ }
50
+ export async function status() {
51
+ const creds = getCredentials();
52
+ if (!creds) {
53
+ console.log("Not authenticated. Run: braaand auth login");
54
+ return;
55
+ }
56
+ console.log(`Authenticated (key: ${creds.apiKey.slice(0, 11)}...)`);
57
+ // Try to fetch brands as a connectivity test
58
+ try {
59
+ const brands = (await apiFetch("/api/brands"));
60
+ console.log(`Connected — ${brands.length} brand(s) accessible`);
61
+ }
62
+ catch (err) {
63
+ console.log(`Key stored but API unreachable: ${err}`);
64
+ }
65
+ }
66
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function list(): Promise<void>;
2
+ export declare function create(name: string, description?: string): Promise<void>;
3
+ export declare function get(brandId: string): Promise<void>;
4
+ export declare function config(brandId: string): Promise<void>;
5
+ export declare function info(brandId: string): Promise<void>;
6
+ export declare function knowledge(brandId: string, sectionId?: string): Promise<void>;
7
+ export declare function portal(brandId: string): Promise<void>;
@@ -0,0 +1,86 @@
1
+ import { apiFetch } from "../api.js";
2
+ import { getConfig } from "../config.js";
3
+ export async function list() {
4
+ const brands = await apiFetch("/api/brands");
5
+ console.log(JSON.stringify(brands, null, 2));
6
+ }
7
+ export async function create(name, description) {
8
+ if (!name) {
9
+ console.error("Usage: braaand brands create <name> [--description <desc>]");
10
+ process.exit(1);
11
+ }
12
+ const brand = await apiFetch("/api/brands", {
13
+ method: "POST",
14
+ body: JSON.stringify({ name, description }),
15
+ });
16
+ console.log(JSON.stringify(brand, null, 2));
17
+ }
18
+ export async function get(brandId) {
19
+ if (!brandId) {
20
+ console.error("Usage: braaand brands get <brandId>");
21
+ process.exit(1);
22
+ }
23
+ const brand = await apiFetch(`/api/brands/${brandId}`);
24
+ console.log(JSON.stringify(brand, null, 2));
25
+ }
26
+ export async function config(brandId) {
27
+ if (!brandId) {
28
+ console.error("Usage: braaand brands config <brandId>");
29
+ process.exit(1);
30
+ }
31
+ const brandConfig = await apiFetch(`/api/brands/${brandId}/brand-config`);
32
+ console.log(JSON.stringify(brandConfig, null, 2));
33
+ }
34
+ export async function info(brandId) {
35
+ if (!brandId) {
36
+ console.error("Usage: braaand brands info <brandId>");
37
+ process.exit(1);
38
+ }
39
+ const apiUrl = getConfig().apiUrl;
40
+ const [brand, brandConfig, assets] = await Promise.all([
41
+ apiFetch(`/api/brands/${brandId}`),
42
+ apiFetch(`/api/brands/${brandId}/brand-config`),
43
+ apiFetch(`/api/brands/${brandId}/assets`),
44
+ ]);
45
+ // Enrich assets with URLs
46
+ const enrichedAssets = assets.map((a) => ({
47
+ ...a,
48
+ url: `${apiUrl}/api/brands/${brandId}/assets/${a.id}`,
49
+ }));
50
+ console.log(JSON.stringify({ brand, brandConfig, assets: enrichedAssets }, null, 2));
51
+ }
52
+ export async function knowledge(brandId, sectionId) {
53
+ if (!brandId) {
54
+ console.error("Usage: braaand brands knowledge <brandId> [sectionId]");
55
+ process.exit(1);
56
+ }
57
+ const config = (await apiFetch(`/api/brands/${brandId}/brand-config`));
58
+ const sections = config.brandKnowledge || [];
59
+ if (sectionId) {
60
+ const section = sections.find((s) => s.id === sectionId);
61
+ if (!section) {
62
+ console.error(`Section "${sectionId}" not found. Available: ${sections.map((s) => s.id).join(", ") || "none"}`);
63
+ process.exit(1);
64
+ }
65
+ console.log(JSON.stringify(section, null, 2));
66
+ }
67
+ else {
68
+ console.log(JSON.stringify(sections, null, 2));
69
+ }
70
+ }
71
+ export async function portal(brandId) {
72
+ if (!brandId) {
73
+ console.error("Usage: braaand brands portal <brandId>");
74
+ process.exit(1);
75
+ }
76
+ const apiUrl = getConfig().apiUrl;
77
+ const url = `${apiUrl}/portal/${brandId}`;
78
+ console.log(url);
79
+ try {
80
+ const { exec } = await import("child_process");
81
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
82
+ exec(`${cmd} "${url}"`);
83
+ }
84
+ catch { }
85
+ }
86
+ //# sourceMappingURL=brands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brands.js","sourceRoot":"","sources":["../../src/commands/brands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function onboard(file?: string): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { apiFetch } from "../api.js";
2
+ import { readFileSync } from "fs";
3
+ export async function onboard(file) {
4
+ let input;
5
+ if (file) {
6
+ input = readFileSync(file, "utf-8");
7
+ }
8
+ else {
9
+ // Read from stdin
10
+ const chunks = [];
11
+ for await (const chunk of process.stdin) {
12
+ chunks.push(chunk);
13
+ }
14
+ input = Buffer.concat(chunks).toString("utf-8");
15
+ }
16
+ if (!input.trim()) {
17
+ console.error("Usage: braaand onboard <file.json>");
18
+ console.error(" or: cat brand.json | braaand onboard");
19
+ process.exit(1);
20
+ }
21
+ let payload;
22
+ try {
23
+ payload = JSON.parse(input);
24
+ }
25
+ catch {
26
+ console.error("Invalid JSON input");
27
+ process.exit(1);
28
+ }
29
+ const result = await apiFetch("/api/onboard", {
30
+ method: "POST",
31
+ body: JSON.stringify(payload),
32
+ });
33
+ console.log(JSON.stringify(result, null, 2));
34
+ }
35
+ //# sourceMappingURL=onboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa;IACzC,IAAI,KAAa,CAAC;IAElB,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;QAC/B,CAAC;QACD,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE;QAC5C,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;KAC9B,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function render(brandId: string, templateId: string, options: {
2
+ format?: string;
3
+ output?: string;
4
+ overrides?: string;
5
+ }): Promise<void>;
@@ -0,0 +1,45 @@
1
+ import { getConfig, getApiKey } from "../config.js";
2
+ import { writeFileSync } from "fs";
3
+ export async function render(brandId, templateId, options) {
4
+ if (!brandId || !templateId) {
5
+ console.error("Usage: braaand render <brandId> <templateId> [--format 1x1] [--output file.png] [--overrides '{...}']");
6
+ process.exit(1);
7
+ }
8
+ const body = { brandId, templateId };
9
+ if (options.format)
10
+ body.format = options.format;
11
+ if (options.overrides) {
12
+ try {
13
+ body.elementOverrides = JSON.parse(options.overrides);
14
+ }
15
+ catch {
16
+ console.error("Invalid JSON in --overrides");
17
+ process.exit(1);
18
+ }
19
+ }
20
+ const config = getConfig();
21
+ const apiKey = getApiKey();
22
+ if (!apiKey) {
23
+ console.error("Not authenticated. Run: braaand auth login");
24
+ process.exit(1);
25
+ }
26
+ const res = await fetch(`${config.apiUrl}/api/render`, {
27
+ method: "POST",
28
+ headers: {
29
+ "Authorization": `Bearer ${apiKey}`,
30
+ "Content-Type": "application/json",
31
+ },
32
+ body: JSON.stringify(body),
33
+ });
34
+ if (!res.ok) {
35
+ const text = await res.text();
36
+ console.error(`Render failed: ${res.status} ${text}`);
37
+ process.exit(1);
38
+ }
39
+ const renderId = res.headers.get("x-render-id") ?? "render";
40
+ const buffer = Buffer.from(await res.arrayBuffer());
41
+ const filename = options.output ?? `${renderId}.png`;
42
+ writeFileSync(filename, buffer);
43
+ console.log(`Rendered to ${filename} (${buffer.length} bytes)`);
44
+ }
45
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAe,EACf,UAAkB,EAClB,OAAiE;IAEjE,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,uGAAuG,CAAC,CAAC;QACvH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAA4B,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACjD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,aAAa,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,eAAe,EAAE,UAAU,MAAM,EAAE;YACnC,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,QAAQ,MAAM,CAAC;IAErD,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,KAAK,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function sync(brandId?: string, dir?: string): Promise<void>;
@@ -0,0 +1,188 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync, rmSync } from "fs";
2
+ import { join, extname } from "path";
3
+ import { apiFetch } from "../api.js";
4
+ import { getConfig, getApiKey } from "../config.js";
5
+ const TYPE_FOLDERS = {
6
+ font: "fonts",
7
+ logo: "logos",
8
+ symbol: "logos",
9
+ image: "images",
10
+ icon: "icons",
11
+ document: "docs",
12
+ };
13
+ function sanitizeFilename(name, ext) {
14
+ // Convert to filesystem-safe name
15
+ const clean = name
16
+ .replace(/[<>:"/\\|?*]/g, "-")
17
+ .replace(/\s+/g, "-")
18
+ .replace(/-+/g, "-")
19
+ .replace(/(^-|-$)/g, "")
20
+ .toLowerCase();
21
+ // Ensure correct extension
22
+ if (clean.endsWith(ext))
23
+ return clean;
24
+ return `${clean}${ext}`;
25
+ }
26
+ function getExtension(filename, mimeType) {
27
+ const ext = extname(filename).toLowerCase();
28
+ if (ext)
29
+ return ext;
30
+ // Fallback to mime type
31
+ const MIME_EXT = {
32
+ "image/svg+xml": ".svg", "image/png": ".png", "image/jpeg": ".jpg",
33
+ "image/webp": ".webp", "font/ttf": ".ttf", "font/otf": ".otf",
34
+ "font/woff": ".woff", "font/woff2": ".woff2", "application/pdf": ".pdf",
35
+ };
36
+ return MIME_EXT[mimeType] || ".bin";
37
+ }
38
+ async function downloadAsset(brandId, assetId, destPath) {
39
+ const config = getConfig();
40
+ const apiKey = getApiKey();
41
+ const url = `${config.apiUrl}/api/brands/${brandId}/assets/${assetId}`;
42
+ const res = await fetch(url, {
43
+ headers: { "Authorization": `Bearer ${apiKey}` },
44
+ });
45
+ if (!res.ok)
46
+ throw new Error(`Failed to download asset ${assetId}: ${res.status}`);
47
+ const buffer = Buffer.from(await res.arrayBuffer());
48
+ writeFileSync(destPath, buffer);
49
+ }
50
+ function loadSyncMetadata(brandDir) {
51
+ const metaPath = join(brandDir, ".braaand.json");
52
+ try {
53
+ return JSON.parse(readFileSync(metaPath, "utf-8"));
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ function saveSyncMetadata(brandDir, meta) {
60
+ writeFileSync(join(brandDir, ".braaand.json"), JSON.stringify(meta, null, 2));
61
+ }
62
+ async function syncBrand(brandId, baseDir) {
63
+ // Fetch brand config and assets in parallel
64
+ const [config, assets] = await Promise.all([
65
+ apiFetch(`/api/brands/${brandId}/brand-config`),
66
+ apiFetch(`/api/brands/${brandId}/assets`),
67
+ ]);
68
+ // Use syncName from config as folder name, fall back to brandId
69
+ const folderName = config.syncName || brandId;
70
+ const brandDir = join(baseDir, folderName);
71
+ // Load previous sync state
72
+ const prevMeta = loadSyncMetadata(brandDir);
73
+ const prevAssets = prevMeta?.assets || {};
74
+ // Ensure directory structure
75
+ mkdirSync(brandDir, { recursive: true });
76
+ const usedFolders = new Set();
77
+ // Write brand.json
78
+ writeFileSync(join(brandDir, "brand.json"), JSON.stringify(config, null, 2));
79
+ console.log(` brand.json`);
80
+ // Track current assets
81
+ const currentAssets = {};
82
+ let downloaded = 0;
83
+ let skipped = 0;
84
+ let removed = 0;
85
+ // Download assets
86
+ for (const asset of assets) {
87
+ // Determine folder — check mime type for PDFs that may be typed as "image"
88
+ const isPdf = asset.mimeType === "application/pdf" || asset.filename.endsWith(".pdf");
89
+ const folder = isPdf ? "docs" : (TYPE_FOLDERS[asset.type] || "other");
90
+ usedFolders.add(folder);
91
+ const folderPath = join(brandDir, folder);
92
+ mkdirSync(folderPath, { recursive: true });
93
+ const ext = getExtension(asset.filename, asset.mimeType);
94
+ const localName = sanitizeFilename(asset.name, ext);
95
+ const destPath = join(folderPath, localName);
96
+ // Check if we already have this asset
97
+ const prev = prevAssets[asset.id];
98
+ const needsDownload = !prev
99
+ || prev.filename !== localName
100
+ || !existsSync(destPath);
101
+ if (needsDownload) {
102
+ // If renamed, remove old file
103
+ if (prev && prev.filename !== localName) {
104
+ const oldFolder = TYPE_FOLDERS[prev.type] || "other";
105
+ const oldPath = join(brandDir, oldFolder, prev.filename);
106
+ try {
107
+ unlinkSync(oldPath);
108
+ }
109
+ catch { /* already gone */ }
110
+ }
111
+ await downloadAsset(brandId, asset.id, destPath);
112
+ console.log(` ${folder}/${localName}`);
113
+ downloaded++;
114
+ }
115
+ else {
116
+ skipped++;
117
+ }
118
+ currentAssets[asset.id] = {
119
+ name: asset.name,
120
+ type: asset.type,
121
+ filename: localName,
122
+ };
123
+ }
124
+ // Remove assets that no longer exist
125
+ const currentIds = new Set(Object.keys(currentAssets));
126
+ for (const [id, prev] of Object.entries(prevAssets)) {
127
+ if (!currentIds.has(id)) {
128
+ const folder = TYPE_FOLDERS[prev.type] || "other";
129
+ const filePath = join(brandDir, folder, prev.filename);
130
+ try {
131
+ unlinkSync(filePath);
132
+ console.log(` removed ${folder}/${prev.filename}`);
133
+ removed++;
134
+ }
135
+ catch { /* already gone */ }
136
+ }
137
+ }
138
+ // Clean up empty type folders
139
+ for (const folder of Object.values(TYPE_FOLDERS)) {
140
+ const folderPath = join(brandDir, folder);
141
+ if (existsSync(folderPath)) {
142
+ try {
143
+ const contents = readdirSync(folderPath);
144
+ if (contents.length === 0) {
145
+ rmSync(folderPath, { recursive: true });
146
+ }
147
+ }
148
+ catch { /* ignore */ }
149
+ }
150
+ }
151
+ // Save sync metadata
152
+ saveSyncMetadata(brandDir, {
153
+ brandId,
154
+ lastSync: new Date().toISOString(),
155
+ assets: currentAssets,
156
+ });
157
+ const parts = [];
158
+ if (downloaded > 0)
159
+ parts.push(`${downloaded} downloaded`);
160
+ if (skipped > 0)
161
+ parts.push(`${skipped} unchanged`);
162
+ if (removed > 0)
163
+ parts.push(`${removed} removed`);
164
+ console.log(` Done — ${parts.join(", ") || "up to date"}`);
165
+ return folderName;
166
+ }
167
+ export async function sync(brandId, dir) {
168
+ const baseDir = dir || process.cwd();
169
+ if (brandId) {
170
+ console.log(`Syncing ${brandId}...`);
171
+ await syncBrand(brandId, baseDir);
172
+ }
173
+ else {
174
+ // Sync all accessible brands
175
+ const brands = (await apiFetch("/api/brands"));
176
+ if (brands.length === 0) {
177
+ console.log("No brands accessible.");
178
+ return;
179
+ }
180
+ console.log(`Syncing ${brands.length} brand${brands.length > 1 ? "s" : ""}...\n`);
181
+ for (const brand of brands) {
182
+ console.log(`${brand.name}`);
183
+ await syncBrand(brand.id, baseDir);
184
+ console.log("");
185
+ }
186
+ }
187
+ }
188
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function list(brandId: string): Promise<void>;
2
+ export declare function discover(brandId: string): Promise<void>;
3
+ export declare function get(brandId: string, templateId: string): Promise<void>;
4
+ export declare function systemList(): Promise<void>;
5
+ export declare function systemInstantiate(templateId: string, brandId: string, name?: string): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { apiFetch } from "../api.js";
2
+ export async function list(brandId) {
3
+ if (!brandId) {
4
+ console.error("Usage: braaand templates list <brandId>");
5
+ process.exit(1);
6
+ }
7
+ const templates = await apiFetch(`/api/brands/${brandId}/templates`);
8
+ console.log(JSON.stringify(templates, null, 2));
9
+ }
10
+ export async function discover(brandId) {
11
+ if (!brandId) {
12
+ console.error("Usage: braaand templates discover <brandId>");
13
+ process.exit(1);
14
+ }
15
+ const catalog = await apiFetch(`/api/brands/${brandId}/templates/discover`);
16
+ console.log(JSON.stringify(catalog, null, 2));
17
+ }
18
+ export async function get(brandId, templateId) {
19
+ if (!brandId || !templateId) {
20
+ console.error("Usage: braaand templates get <brandId> <templateId>");
21
+ process.exit(1);
22
+ }
23
+ const template = await apiFetch(`/api/brands/${brandId}/templates/${templateId}`);
24
+ console.log(JSON.stringify(template, null, 2));
25
+ }
26
+ export async function systemList() {
27
+ const catalog = await apiFetch("/api/system-templates");
28
+ console.log(JSON.stringify(catalog, null, 2));
29
+ }
30
+ export async function systemInstantiate(templateId, brandId, name) {
31
+ if (!templateId || !brandId) {
32
+ console.error("Usage: braaand system-templates instantiate <templateId> --brand <brandId> [--name <name>]");
33
+ process.exit(1);
34
+ }
35
+ const result = await apiFetch(`/api/system-templates/${templateId}/instantiate`, {
36
+ method: "POST",
37
+ body: JSON.stringify({ brandId, name }),
38
+ });
39
+ console.log(JSON.stringify(result, null, 2));
40
+ }
41
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/commands/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAe;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,eAAe,OAAO,YAAY,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,OAAO,qBAAqB,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAe,EAAE,UAAkB;IAC3D,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,eAAe,OAAO,cAAc,UAAU,EAAE,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAkB,EAClB,OAAe,EACf,IAAa;IAEb,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,4FAA4F,CAAC,CAAC;QAC5G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,yBAAyB,UAAU,cAAc,EAAE;QAC/E,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,13 @@
1
+ interface Credentials {
2
+ apiKey: string;
3
+ }
4
+ interface Config {
5
+ apiUrl: string;
6
+ }
7
+ export declare function getCredentials(): Credentials | null;
8
+ export declare function saveCredentials(creds: Credentials): void;
9
+ export declare function deleteCredentials(): void;
10
+ export declare function getConfig(): Config;
11
+ export declare function saveConfig(config: Partial<Config>): void;
12
+ export declare function getApiKey(): string | null;
13
+ export {};
package/dist/config.js ADDED
@@ -0,0 +1,50 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ const CONFIG_DIR = join(homedir(), ".braaand");
5
+ const CREDS_FILE = join(CONFIG_DIR, "credentials.json");
6
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
7
+ function ensureDir() {
8
+ if (!existsSync(CONFIG_DIR)) {
9
+ mkdirSync(CONFIG_DIR, { recursive: true });
10
+ }
11
+ }
12
+ export function getCredentials() {
13
+ try {
14
+ const raw = readFileSync(CREDS_FILE, "utf-8");
15
+ return JSON.parse(raw);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export function saveCredentials(creds) {
22
+ ensureDir();
23
+ writeFileSync(CREDS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
24
+ }
25
+ export function deleteCredentials() {
26
+ try {
27
+ unlinkSync(CREDS_FILE);
28
+ }
29
+ catch {
30
+ // already gone
31
+ }
32
+ }
33
+ export function getConfig() {
34
+ try {
35
+ const raw = readFileSync(CONFIG_FILE, "utf-8");
36
+ return { apiUrl: "https://braaand.ai", ...JSON.parse(raw) };
37
+ }
38
+ catch {
39
+ return { apiUrl: "https://braaand.ai" };
40
+ }
41
+ }
42
+ export function saveConfig(config) {
43
+ ensureDir();
44
+ const existing = getConfig();
45
+ writeFileSync(CONFIG_FILE, JSON.stringify({ ...existing, ...config }, null, 2));
46
+ }
47
+ export function getApiKey() {
48
+ return getCredentials()?.apiKey ?? null;
49
+ }
50
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AACxD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAUpD,SAAS,SAAS;IAChB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,SAAS,EAAE,CAAC;IACZ,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,UAAU,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAuB;IAChD,SAAS,EAAE,CAAC;IACZ,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,cAAc,EAAE,EAAE,MAAM,IAAI,IAAI,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ import { login, logout, status } from "./commands/auth.js";
3
+ import * as assets from "./commands/assets.js";
4
+ import * as brands from "./commands/brands.js";
5
+ import * as templates from "./commands/templates.js";
6
+ import { render } from "./commands/render.js";
7
+ import { onboard } from "./commands/onboard.js";
8
+ import { sync } from "./commands/sync.js";
9
+ import { saveConfig } from "./config.js";
10
+ const args = process.argv.slice(2);
11
+ const command = args[0];
12
+ const subcommand = args[1];
13
+ function getFlag(name) {
14
+ const idx = args.indexOf(`--${name}`);
15
+ return idx >= 0 ? args[idx + 1] : undefined;
16
+ }
17
+ function printHelp() {
18
+ console.log(`
19
+ braaand — CLI for Braaand
20
+
21
+ USAGE
22
+ braaand <command> [subcommand] [options]
23
+
24
+ AUTH
25
+ auth login Authenticate via browser (device flow)
26
+ auth logout Remove stored credentials
27
+ auth status Show auth status and test connectivity
28
+
29
+ ASSETS
30
+ assets list <brandId>
31
+ assets upload <brandId> <file> [--name <name>] [--type logo|image|font|icon|symbol] [--tags <comma-sep>]
32
+
33
+ BRANDS
34
+ brands list List your brands
35
+ brands create <name> [--description <desc>]
36
+ brands get <id> Get brand details
37
+ brands config <id> Get brand config (colors, fonts, voice, tokens)
38
+ brands info <id> Full brand dump (config + assets with URLs)
39
+ brands knowledge <id> [sectionId] Query brand knowledge sections
40
+ brands portal <id> Open brand portal in browser
41
+
42
+ TEMPLATES
43
+ templates list <brandId>
44
+ templates get <brandId> <templateId>
45
+ templates discover <brandId> Full agent-facing catalog
46
+
47
+ SYSTEM TEMPLATES
48
+ system-templates list
49
+ system-templates instantiate <templateId> --brand <brandId> [--name <name>]
50
+
51
+ RENDER
52
+ render <brandId> <templateId> [--format 1x1] [--output file.png] [--overrides '{...}']
53
+
54
+ SYNC
55
+ sync [brandId] Sync brand assets to local folders
56
+ sync --dir <path> Sync into a specific directory (default: cwd)
57
+
58
+ ONBOARD
59
+ onboard <file.json> Create brand + config + assets from JSON
60
+ cat brand.json | onboard Pipe JSON from stdin
61
+
62
+ CONFIG
63
+ config set-url <url> Set API URL (default: https://braaand.ai)
64
+
65
+ OUTPUT
66
+ All commands output JSON to stdout. Pipe to jq for formatting:
67
+ braaand brands list | jq '.[].name'
68
+ `);
69
+ }
70
+ async function main() {
71
+ try {
72
+ switch (command) {
73
+ case "auth":
74
+ switch (subcommand) {
75
+ case "login": return await login();
76
+ case "logout": return logout();
77
+ case "status": return await status();
78
+ default: return printHelp();
79
+ }
80
+ case "assets":
81
+ switch (subcommand) {
82
+ case "list": return await assets.list(args[2]);
83
+ case "upload":
84
+ return await assets.upload(args[2], args[3], {
85
+ name: getFlag("name"),
86
+ type: getFlag("type"),
87
+ tags: getFlag("tags"),
88
+ description: getFlag("description"),
89
+ });
90
+ default: return printHelp();
91
+ }
92
+ case "brands":
93
+ switch (subcommand) {
94
+ case "list": return await brands.list();
95
+ case "create": return await brands.create(args[2], getFlag("description"));
96
+ case "get": return await brands.get(args[2]);
97
+ case "config": return await brands.config(args[2]);
98
+ case "info": return await brands.info(args[2]);
99
+ case "knowledge": return await brands.knowledge(args[2], args[3]);
100
+ case "portal": return await brands.portal(args[2]);
101
+ default: return printHelp();
102
+ }
103
+ case "templates":
104
+ switch (subcommand) {
105
+ case "list": return await templates.list(args[2]);
106
+ case "get": return await templates.get(args[2], args[3]);
107
+ case "discover": return await templates.discover(args[2]);
108
+ default: return printHelp();
109
+ }
110
+ case "system-templates":
111
+ switch (subcommand) {
112
+ case "list": return await templates.systemList();
113
+ case "instantiate":
114
+ return await templates.systemInstantiate(args[2], getFlag("brand"), getFlag("name"));
115
+ default: return printHelp();
116
+ }
117
+ case "render":
118
+ return await render(args[1], args[2], {
119
+ format: getFlag("format"),
120
+ output: getFlag("output"),
121
+ overrides: getFlag("overrides"),
122
+ });
123
+ case "sync": {
124
+ const syncBrandId = args[1]?.startsWith("--") ? undefined : args[1];
125
+ return await sync(syncBrandId, getFlag("dir"));
126
+ }
127
+ case "onboard":
128
+ return await onboard(args[1]);
129
+ case "config":
130
+ if (subcommand === "set-url" && args[2]) {
131
+ saveConfig({ apiUrl: args[2] });
132
+ console.log(`API URL set to ${args[2]}`);
133
+ return;
134
+ }
135
+ return printHelp();
136
+ case "help":
137
+ case "--help":
138
+ case "-h":
139
+ case undefined:
140
+ return printHelp();
141
+ default:
142
+ console.error(`Unknown command: ${command}`);
143
+ printHelp();
144
+ process.exit(1);
145
+ }
146
+ }
147
+ catch (err) {
148
+ if (err instanceof Error) {
149
+ console.error(`Error: ${err.message}`);
150
+ }
151
+ else {
152
+ console.error(err);
153
+ }
154
+ process.exit(1);
155
+ }
156
+ }
157
+ main();
158
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "braaand",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Braaand — brand infrastructure for agentic automation",
5
+ "type": "module",
6
+ "bin": {
7
+ "braaand": "./dist/index.js"
8
+ },
9
+ "files": ["dist", "package.json"],
10
+ "engines": { "node": ">=20" },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5.0.0",
17
+ "@types/node": "^20.0.0"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Nitti AI",
21
+ "homepage": "https://braaand.ai",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/nitti-ai/cb-ad-engine.git",
25
+ "directory": "packages/cli"
26
+ },
27
+ "keywords": ["brand", "ai", "cli", "templates", "assets", "braaand"]
28
+ }