create-hedgeboard 1.0.2 → 1.0.4
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/index.js +87 -25
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -62,7 +62,7 @@ function parseArgs() {
|
|
|
62
62
|
if (!opts.key) {
|
|
63
63
|
console.error(
|
|
64
64
|
"Error: --key is required.\n" +
|
|
65
|
-
" Get your API key at https://
|
|
65
|
+
" Get your API key at https://www.hedgeboardhq.com/dashboard\n\n" +
|
|
66
66
|
" Usage: npx create-hedgeboard --key YOUR_API_KEY"
|
|
67
67
|
);
|
|
68
68
|
process.exit(1);
|
|
@@ -111,6 +111,44 @@ function extractZip(zipBuffer, destDir) {
|
|
|
111
111
|
fs.unlinkSync(tmpZip);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Colors (ANSI escape codes — zero dependencies)
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
const c = {
|
|
119
|
+
reset: "\x1b[0m",
|
|
120
|
+
bold: "\x1b[1m",
|
|
121
|
+
dim: "\x1b[2m",
|
|
122
|
+
green: "\x1b[32m",
|
|
123
|
+
cyan: "\x1b[36m",
|
|
124
|
+
yellow: "\x1b[33m",
|
|
125
|
+
magenta: "\x1b[35m",
|
|
126
|
+
gray: "\x1b[90m",
|
|
127
|
+
white: "\x1b[97m",
|
|
128
|
+
bgGreen: "\x1b[42m",
|
|
129
|
+
underline: "\x1b[4m",
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
function banner() {
|
|
133
|
+
const bk = "\x1b[30m"; // black
|
|
134
|
+
const dg = "\x1b[90m"; // dark gray
|
|
135
|
+
console.log(`
|
|
136
|
+
${bk}${c.bold} ██╗ ██╗███████╗██████╗ ██████╗ ███████╗${c.reset}
|
|
137
|
+
${bk}${c.bold} ██║ ██║██╔════╝██╔══██╗██╔════╝ ██╔════╝${c.reset}
|
|
138
|
+
${bk}${c.bold} ███████║█████╗ ██║ ██║██║ ███╗█████╗ ${c.reset}
|
|
139
|
+
${bk}${c.bold} ██╔══██║██╔══╝ ██║ ██║██║ ██║██╔══╝ ${c.reset}
|
|
140
|
+
${bk}${c.bold} ██║ ██║███████╗██████╔╝╚██████╔╝███████╗${c.reset}
|
|
141
|
+
${bk}${c.bold} ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚══════╝${c.reset}
|
|
142
|
+
${dg}${c.bold} ██████╗ ██████╗ █████╗ ██████╗ ██████╗ ${c.reset}
|
|
143
|
+
${dg}${c.bold} ██╔══██╗██╔═══██╗██╔══██╗██╔══██╗██╔══██╗${c.reset}
|
|
144
|
+
${dg}${c.bold} ██████╔╝██║ ██║███████║██████╔╝██║ ██║${c.reset}
|
|
145
|
+
${dg}${c.bold} ██╔══██╗██║ ██║██╔══██║██╔══██╗██║ ██║${c.reset}
|
|
146
|
+
${dg}${c.bold} ██████╔╝╚██████╔╝██║ ██║██║ ██║██████╔╝${c.reset}
|
|
147
|
+
${dg}${c.bold} ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ${c.reset}
|
|
148
|
+
${c.dim} AI-Native Financial Intelligence — v1.0.4${c.reset}
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
|
|
114
152
|
// ---------------------------------------------------------------------------
|
|
115
153
|
// Main
|
|
116
154
|
// ---------------------------------------------------------------------------
|
|
@@ -118,36 +156,34 @@ function extractZip(zipBuffer, destDir) {
|
|
|
118
156
|
async function main() {
|
|
119
157
|
const { key, dir } = parseArgs();
|
|
120
158
|
|
|
121
|
-
|
|
122
|
-
console.log(" ║ create-hedgeboard ║");
|
|
123
|
-
console.log(" ╚══════════════════════════════════════╝\n");
|
|
159
|
+
banner();
|
|
124
160
|
|
|
125
161
|
// 1. Validate API key against the app
|
|
126
|
-
process.stdout.write(
|
|
162
|
+
process.stdout.write(` ${c.gray}◆${c.reset} Validating API key ${c.dim}...${c.reset} `);
|
|
127
163
|
try {
|
|
128
164
|
const resp = await fetchBuffer(`${APP_URL}/api/data-sources?key=${key}`);
|
|
129
165
|
const data = JSON.parse(resp.toString());
|
|
130
166
|
if (data.error) throw new Error(data.error);
|
|
131
|
-
console.log(
|
|
167
|
+
console.log(`${c.green}✓${c.reset}`);
|
|
132
168
|
} catch (err) {
|
|
133
|
-
console.log(
|
|
169
|
+
console.log(`${c.green}✓${c.reset} ${c.dim}(offline)${c.reset}`);
|
|
134
170
|
}
|
|
135
171
|
|
|
136
172
|
// 2. Download toolkit from S3
|
|
137
|
-
process.stdout.write(
|
|
173
|
+
process.stdout.write(` ${c.gray}◆${c.reset} Downloading toolkit ${c.dim}...${c.reset} `);
|
|
138
174
|
let zipBuffer;
|
|
139
175
|
try {
|
|
140
176
|
zipBuffer = await fetchBuffer(S3_TOOLKIT_URL);
|
|
141
|
-
console.log(
|
|
177
|
+
console.log(`${c.green}✓${c.reset} ${c.dim}${(zipBuffer.length / 1024).toFixed(0)} KB${c.reset}`);
|
|
142
178
|
} catch (err) {
|
|
143
|
-
console.log(
|
|
144
|
-
console.error(
|
|
179
|
+
console.log(`${c.yellow}✗${c.reset}`);
|
|
180
|
+
console.error(`\n ${c.yellow}Error:${c.reset} Failed to download toolkit. Check your internet connection.`);
|
|
145
181
|
process.exit(1);
|
|
146
182
|
}
|
|
147
183
|
|
|
148
184
|
// 3. Extract to temp, then move to target dir
|
|
149
185
|
const absDir = path.resolve(dir);
|
|
150
|
-
process.stdout.write(`
|
|
186
|
+
process.stdout.write(` ${c.gray}◆${c.reset} Extracting workspace ${c.dim}...${c.reset} `);
|
|
151
187
|
try {
|
|
152
188
|
const tmpDir = path.join(require("os").tmpdir(), `hb-extract-${Date.now()}`);
|
|
153
189
|
extractZip(zipBuffer, tmpDir);
|
|
@@ -155,41 +191,67 @@ async function main() {
|
|
|
155
191
|
// The ZIP contains hedgeboard/ folder — move its contents to target
|
|
156
192
|
const extractedDir = path.join(tmpDir, "hedgeboard");
|
|
157
193
|
if (fs.existsSync(extractedDir)) {
|
|
158
|
-
// Move extracted hedgeboard/ to the user's target dir
|
|
159
194
|
fs.mkdirSync(path.dirname(absDir), { recursive: true });
|
|
160
195
|
if (fs.existsSync(absDir)) {
|
|
161
|
-
// Merge into existing dir
|
|
162
196
|
const { execSync } = require("child_process");
|
|
163
197
|
execSync(`cp -r "${extractedDir}/"* "${absDir}/"`);
|
|
164
198
|
} else {
|
|
165
199
|
fs.renameSync(extractedDir, absDir);
|
|
166
200
|
}
|
|
167
201
|
}
|
|
168
|
-
// Cleanup temp
|
|
169
202
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
170
|
-
console.log(
|
|
203
|
+
console.log(`${c.green}✓${c.reset}`);
|
|
171
204
|
} catch (err) {
|
|
172
|
-
console.log(
|
|
173
|
-
console.error(
|
|
205
|
+
console.log(`${c.yellow}✗${c.reset}`);
|
|
206
|
+
console.error(`\n ${c.yellow}Error:${c.reset} Failed to extract toolkit.`, err.message);
|
|
174
207
|
process.exit(1);
|
|
175
208
|
}
|
|
176
209
|
|
|
177
210
|
// 4. Write .env with the user's API key
|
|
211
|
+
process.stdout.write(` ${c.gray}◆${c.reset} Configuring API key ${c.dim}...${c.reset} `);
|
|
178
212
|
const envPath = path.join(absDir, ".env");
|
|
179
213
|
fs.writeFileSync(
|
|
180
214
|
envPath,
|
|
181
215
|
`# HedgeBoard API\nHEDGEBOARD_API_KEY=${key}\nHEDGEBOARD_API_URL=${API_URL}\n`
|
|
182
216
|
);
|
|
217
|
+
console.log(`${c.green}✓${c.reset}`);
|
|
218
|
+
|
|
219
|
+
// 5. Summary
|
|
220
|
+
const relDir = path.relative(process.cwd(), absDir) || ".";
|
|
221
|
+
|
|
222
|
+
console.log(`
|
|
223
|
+
${c.green}${c.bold}✓ HedgeBoard workspace ready${c.reset}
|
|
224
|
+
${c.dim} ─────────────────────────────────────${c.reset}
|
|
183
225
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
226
|
+
${c.bold}Directory${c.reset} ${c.cyan}${relDir}/${c.reset}
|
|
227
|
+
${c.bold}API Key${c.reset} ${c.dim}${key.slice(0, 8)}${"•".repeat(12)}${key.slice(-4)}${c.reset}
|
|
228
|
+
${c.bold}API URL${c.reset} ${c.dim}${API_URL}${c.reset}
|
|
229
|
+
|
|
230
|
+
${c.bold}What's inside:${c.reset}
|
|
231
|
+
${c.gray}├──${c.reset} ${c.white}CLAUDE.md${c.reset} ${c.dim}Agent instructions & prompt${c.reset}
|
|
232
|
+
${c.gray}├──${c.reset} ${c.white}data/${c.reset} ${c.dim}SEC data fetching modules${c.reset}
|
|
233
|
+
${c.gray}├──${c.reset} ${c.white}viz/${c.reset} ${c.dim}Dashboard templates & charts${c.reset}
|
|
234
|
+
${c.gray}├──${c.reset} ${c.white}brand/${c.reset} ${c.dim}Your brand settings${c.reset}
|
|
235
|
+
${c.gray}├──${c.reset} ${c.white}modules/${c.reset} ${c.dim}Shared helpers${c.reset}
|
|
236
|
+
${c.gray}└──${c.reset} ${c.white}output/${c.reset} ${c.dim}Generated dashboards land here${c.reset}
|
|
237
|
+
|
|
238
|
+
${c.dim} ─────────────────────────────────────${c.reset}
|
|
239
|
+
|
|
240
|
+
${c.bold}Next steps:${c.reset}
|
|
241
|
+
|
|
242
|
+
${c.cyan}1.${c.reset} Open in Claude Code:
|
|
243
|
+
${c.dim}$${c.reset} ${c.white}cd ${relDir} && claude${c.reset}
|
|
244
|
+
|
|
245
|
+
${c.cyan}2.${c.reset} Ask something:
|
|
246
|
+
${c.magenta}"Give me a company overview of Apple"${c.reset}
|
|
247
|
+
|
|
248
|
+
${c.cyan}3.${c.reset} Customize your brand at:
|
|
249
|
+
${c.underline}https://www.hedgeboardhq.com/dashboard${c.reset}
|
|
250
|
+
`);
|
|
190
251
|
}
|
|
191
252
|
|
|
192
253
|
main().catch((err) => {
|
|
193
|
-
console.error(
|
|
254
|
+
console.error(`\n ${c.yellow}Unexpected error:${c.reset}`, err.message);
|
|
194
255
|
process.exit(1);
|
|
195
256
|
});
|
|
257
|
+
|