hacklab 0.4.2 → 0.5.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 +3 -0
- package/dist/commands/chat.d.ts +5 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +359 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/company.d.ts +2 -0
- package/dist/commands/company.d.ts.map +1 -0
- package/dist/commands/company.js +214 -0
- package/dist/commands/company.js.map +1 -0
- package/dist/commands/org.d.ts +2 -0
- package/dist/commands/org.d.ts.map +1 -0
- package/dist/commands/org.js +214 -0
- package/dist/commands/org.js.map +1 -0
- package/dist/index.js +30 -10
- package/dist/index.js.map +1 -1
- package/dist/resolve-command.d.ts +21 -0
- package/dist/resolve-command.d.ts.map +1 -0
- package/dist/resolve-command.js +36 -0
- package/dist/resolve-command.js.map +1 -0
- package/dist/share-card-colors.d.ts +19 -0
- package/dist/share-card-colors.d.ts.map +1 -0
- package/dist/share-card-colors.js +36 -0
- package/dist/share-card-colors.js.map +1 -0
- package/dist/share-card.d.ts.map +1 -1
- package/dist/share-card.js +22 -21
- package/dist/share-card.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { loadSession } from '../session.js';
|
|
3
|
+
import { bold, dim, error, info, success } from '../ui.js';
|
|
4
|
+
const FIELDS = [
|
|
5
|
+
{ key: 'name', label: 'Name', type: 'text' },
|
|
6
|
+
{ key: 'slug', label: 'Slug (URL handle)', type: 'text' },
|
|
7
|
+
{ key: 'logoUrl', label: 'Logo URL', type: 'url' },
|
|
8
|
+
{ key: 'website', label: 'Website', type: 'url' },
|
|
9
|
+
{ key: 'description', label: 'Short description', type: 'text' },
|
|
10
|
+
{ key: 'longDescription', label: 'Long description', type: 'text' },
|
|
11
|
+
{ key: 'ycBatch', label: 'YC batch', type: 'text' },
|
|
12
|
+
{ key: 'ycSlug', label: 'YC slug', type: 'text' },
|
|
13
|
+
{ key: 'ycUrl', label: 'YC URL', type: 'url' },
|
|
14
|
+
{ key: 'waasUrl', label: 'WaaS URL', type: 'url' },
|
|
15
|
+
{ key: 'teamSize', label: 'Team size', type: 'number' },
|
|
16
|
+
{ key: 'status', label: 'Status', type: 'text' },
|
|
17
|
+
{ key: 'stage', label: 'Stage', type: 'text' },
|
|
18
|
+
{ key: 'isHiring', label: 'Hiring?', type: 'boolean' },
|
|
19
|
+
{ key: 'industries', label: 'Industries', type: 'list' },
|
|
20
|
+
{ key: 'tags', label: 'Tags', type: 'list' },
|
|
21
|
+
{ key: 'locations', label: 'Locations', type: 'list' },
|
|
22
|
+
];
|
|
23
|
+
// Short, human label for the current value (shown as a select-menu hint).
|
|
24
|
+
function displayValue(spec, value) {
|
|
25
|
+
if (value == null || value === '')
|
|
26
|
+
return '(empty)';
|
|
27
|
+
if (spec.type === 'boolean')
|
|
28
|
+
return value ? 'yes' : 'no';
|
|
29
|
+
if (spec.type === 'list') {
|
|
30
|
+
return Array.isArray(value) ? value.join(', ') || '(empty)' : String(value);
|
|
31
|
+
}
|
|
32
|
+
const s = String(value);
|
|
33
|
+
return s.length > 48 ? `${s.slice(0, 47)}…` : s;
|
|
34
|
+
}
|
|
35
|
+
async function fetchOrgs(session) {
|
|
36
|
+
const res = await fetch(`${session.appUrl}/api/cli/org`, {
|
|
37
|
+
headers: { Authorization: `Bearer ${session.token}` },
|
|
38
|
+
});
|
|
39
|
+
const data = await res.json().catch(() => null);
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
throw new Error(data?.error ?? `failed to load organizations (${res.status})`);
|
|
42
|
+
}
|
|
43
|
+
return (data?.organizations ?? []);
|
|
44
|
+
}
|
|
45
|
+
async function patchOrg(session, orgId, fields) {
|
|
46
|
+
const res = await fetch(`${session.appUrl}/api/cli/org`, {
|
|
47
|
+
method: 'PATCH',
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
Authorization: `Bearer ${session.token}`,
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify({ orgId, fields }),
|
|
53
|
+
});
|
|
54
|
+
const data = await res.json().catch(() => null);
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
throw new Error(data?.error ?? `update failed (${res.status})`);
|
|
57
|
+
}
|
|
58
|
+
return data;
|
|
59
|
+
}
|
|
60
|
+
// Prompt for one field, prefilled with the current value. Returns the new
|
|
61
|
+
// value to send, or a clack cancel symbol.
|
|
62
|
+
async function promptField(spec, current) {
|
|
63
|
+
if (spec.type === 'boolean') {
|
|
64
|
+
return clack.confirm({
|
|
65
|
+
message: spec.label,
|
|
66
|
+
initialValue: Boolean(current),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (spec.type === 'list') {
|
|
70
|
+
const initial = Array.isArray(current) ? current.join(', ') : '';
|
|
71
|
+
const value = await clack.text({
|
|
72
|
+
message: `${spec.label} ${dim('(comma-separated, blank to clear)')}`,
|
|
73
|
+
initialValue: initial,
|
|
74
|
+
});
|
|
75
|
+
if (clack.isCancel(value))
|
|
76
|
+
return value;
|
|
77
|
+
const items = value
|
|
78
|
+
.split(',')
|
|
79
|
+
.map((s) => s.trim())
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
return items.length ? items : null;
|
|
82
|
+
}
|
|
83
|
+
if (spec.type === 'number') {
|
|
84
|
+
const value = await clack.text({
|
|
85
|
+
message: `${spec.label} ${dim('(blank to clear)')}`,
|
|
86
|
+
initialValue: current == null ? '' : String(current),
|
|
87
|
+
validate: (v) => {
|
|
88
|
+
const t = (v ?? '').trim();
|
|
89
|
+
return !t || /^\d+$/.test(t) ? undefined : 'must be a whole number';
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
if (clack.isCancel(value))
|
|
93
|
+
return value;
|
|
94
|
+
return value.trim() ? Number(value.trim()) : null;
|
|
95
|
+
}
|
|
96
|
+
const value = await clack.text({
|
|
97
|
+
message: spec.type === 'url'
|
|
98
|
+
? `${spec.label} ${dim('(blank to clear)')}`
|
|
99
|
+
: spec.label,
|
|
100
|
+
initialValue: current == null ? '' : String(current),
|
|
101
|
+
validate: spec.type === 'url'
|
|
102
|
+
? (v) => {
|
|
103
|
+
const t = (v ?? '').trim();
|
|
104
|
+
if (!t)
|
|
105
|
+
return undefined;
|
|
106
|
+
try {
|
|
107
|
+
new URL(t);
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return 'must be a valid URL (include https://)';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
: undefined,
|
|
115
|
+
});
|
|
116
|
+
if (clack.isCancel(value))
|
|
117
|
+
return value;
|
|
118
|
+
const trimmed = value.trim();
|
|
119
|
+
// name/slug are required (notNull): a blank keeps the current value.
|
|
120
|
+
if ((spec.key === 'name' || spec.key === 'slug') && !trimmed)
|
|
121
|
+
return current;
|
|
122
|
+
return trimmed ? trimmed : null;
|
|
123
|
+
}
|
|
124
|
+
export async function org() {
|
|
125
|
+
const session = await loadSession();
|
|
126
|
+
if (!session) {
|
|
127
|
+
error('not logged in');
|
|
128
|
+
info(`run ${dim('hacklab login')} first`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
clack.intro(bold('hacklab org'));
|
|
132
|
+
let orgs;
|
|
133
|
+
try {
|
|
134
|
+
orgs = await fetchOrgs(session);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
clack.cancel(err instanceof Error ? err.message : String(err));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
if (orgs.length === 0) {
|
|
141
|
+
clack.cancel(`you don't manage an organization yet — claim one at ${session.appUrl} first.`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
let target = orgs[0];
|
|
145
|
+
if (orgs.length > 1) {
|
|
146
|
+
const picked = await clack.select({
|
|
147
|
+
message: 'which organization?',
|
|
148
|
+
options: orgs.map((o) => ({
|
|
149
|
+
value: o.id,
|
|
150
|
+
label: `${o.name} ${dim(`/o/${o.slug}`)}`,
|
|
151
|
+
})),
|
|
152
|
+
});
|
|
153
|
+
if (clack.isCancel(picked)) {
|
|
154
|
+
clack.outro(dim('cancelled.'));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
target = orgs.find((o) => o.id === picked) ?? target;
|
|
158
|
+
}
|
|
159
|
+
// Autosave: editing a field writes it immediately (mirrors the web settings'
|
|
160
|
+
// "saves instantly, no Save button"). Pick a field, set its value, it saves,
|
|
161
|
+
// and the menu shows the saved value. Leave any time with "done" or Esc —
|
|
162
|
+
// nothing is pending, so nothing is lost.
|
|
163
|
+
const DONE = '__done__';
|
|
164
|
+
let savedCount = 0;
|
|
165
|
+
while (true) {
|
|
166
|
+
const choice = await clack.select({
|
|
167
|
+
message: `editing ${bold(target.name)} ${dim('(saves as you go)')}`,
|
|
168
|
+
options: [
|
|
169
|
+
...FIELDS.map((f) => ({
|
|
170
|
+
value: f.key,
|
|
171
|
+
label: f.label,
|
|
172
|
+
hint: displayValue(f, target[f.key]),
|
|
173
|
+
})),
|
|
174
|
+
{ value: DONE, label: '← done' },
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
// Esc / Ctrl+C at the menu, or "done": leave. Every edit is already saved.
|
|
178
|
+
if (clack.isCancel(choice) || choice === DONE)
|
|
179
|
+
break;
|
|
180
|
+
const spec = FIELDS.find((f) => f.key === choice);
|
|
181
|
+
if (!spec)
|
|
182
|
+
continue;
|
|
183
|
+
const next = await promptField(spec, target[spec.key]);
|
|
184
|
+
// Cancelling a single field drops just that edit and returns to the menu.
|
|
185
|
+
if (clack.isCancel(next))
|
|
186
|
+
continue;
|
|
187
|
+
const label = spec.label.toLowerCase();
|
|
188
|
+
const prevSlug = target.slug;
|
|
189
|
+
const spin = clack.spinner();
|
|
190
|
+
spin.start(`saving ${label}`);
|
|
191
|
+
try {
|
|
192
|
+
const updated = await patchOrg(session, target.id, {
|
|
193
|
+
[spec.key]: next,
|
|
194
|
+
});
|
|
195
|
+
target = { ...target, ...updated };
|
|
196
|
+
savedCount++;
|
|
197
|
+
spin.stop(`saved ${label}`);
|
|
198
|
+
if (spec.key === 'slug' && target.slug !== prevSlug) {
|
|
199
|
+
clack.log.warn(`old links to /o/${prevSlug} will no longer resolve`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
spin.stop(`could not save ${label}`);
|
|
204
|
+
error(err instanceof Error ? err.message : String(err));
|
|
205
|
+
// Stay in the loop so they can retry or edit something else.
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (savedCount > 0) {
|
|
209
|
+
success(`saved ${savedCount} change${savedCount === 1 ? '' : 's'} to ${bold(target.name)}`);
|
|
210
|
+
info(`${session.appUrl}/o/${target.slug}`);
|
|
211
|
+
}
|
|
212
|
+
clack.outro(dim('done.'));
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=org.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org.js","sourceRoot":"","sources":["../../src/commands/org.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { brag, parseBragArgs } from './commands/brag.js';
|
|
3
|
+
import { chat } from './commands/chat.js';
|
|
3
4
|
import { configCommand } from './commands/config.js';
|
|
4
5
|
import { drop } from './commands/drop.js';
|
|
5
6
|
import { exam } from './commands/exam.js';
|
|
6
7
|
import { join } from './commands/join.js';
|
|
7
8
|
import { login } from './commands/login.js';
|
|
9
|
+
import { org } from './commands/org.js';
|
|
8
10
|
import { scanProfile } from './commands/scan-profile.js';
|
|
9
11
|
import { sync } from './commands/sync.js';
|
|
10
12
|
import { whoami } from './commands/whoami.js';
|
|
13
|
+
import { resolveCommand } from './resolve-command.js';
|
|
11
14
|
import { HACKLAB_ENVIRONMENTS, isHacklabEnv, loadSession } from './session.js';
|
|
12
15
|
import { banner, bold, dim } from './ui.js';
|
|
13
16
|
/**
|
|
@@ -54,6 +57,8 @@ function printHelp() {
|
|
|
54
57
|
console.log(` hacklab ${dim('scan')} build your full profile (skills, repos, blog)`);
|
|
55
58
|
console.log(` hacklab ${dim('config')} ${dim('<key> <val>')} set config (cursor-api-key, cursor-email)`);
|
|
56
59
|
console.log(` hacklab ${dim('brag')} ${dim('[path]')} sync .hacklab/project.yaml`);
|
|
60
|
+
console.log(` hacklab ${dim('org')} edit your organization`);
|
|
61
|
+
console.log(` hacklab ${dim('chat')} ${dim('<sub>')} channel + DMs (tail/post/dm/...); --json for agents`);
|
|
57
62
|
console.log('');
|
|
58
63
|
console.log(` ${dim('--env')} ${dim('<production|staging|development>')} pick the backend (default: production)`);
|
|
59
64
|
console.log('');
|
|
@@ -78,7 +83,7 @@ async function main() {
|
|
|
78
83
|
process.exit(0);
|
|
79
84
|
}
|
|
80
85
|
if (cmd === '--version' || cmd === '-v') {
|
|
81
|
-
console.log('0.
|
|
86
|
+
console.log('0.5.0');
|
|
82
87
|
process.exit(0);
|
|
83
88
|
}
|
|
84
89
|
// Bare invocation (e.g. `npx hacklab@latest`): join for newcomers, sync for
|
|
@@ -93,37 +98,52 @@ async function main() {
|
|
|
93
98
|
}
|
|
94
99
|
return;
|
|
95
100
|
}
|
|
96
|
-
|
|
101
|
+
// Resolve a possibly-abbreviated command to its full name (e.g. `sy` -> sync,
|
|
102
|
+
// `or` -> org). Exact matches always win; an ambiguous prefix is
|
|
103
|
+
// rejected with the candidates so the user can disambiguate.
|
|
104
|
+
const resolution = resolveCommand(cmd);
|
|
105
|
+
if (resolution.kind === 'ambiguous') {
|
|
106
|
+
console.error(`ambiguous command "${cmd}": ${resolution.matches.join(' or ')}?`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
const command = resolution.kind === 'match' ? resolution.name : cmd;
|
|
110
|
+
if (command === 'join') {
|
|
97
111
|
await join();
|
|
98
112
|
}
|
|
99
|
-
else if (
|
|
113
|
+
else if (command === 'login') {
|
|
100
114
|
await login();
|
|
101
115
|
}
|
|
102
|
-
else if (
|
|
116
|
+
else if (command === 'whoami') {
|
|
103
117
|
await whoami();
|
|
104
118
|
}
|
|
105
|
-
else if (
|
|
119
|
+
else if (command === 'sync') {
|
|
106
120
|
await sync();
|
|
107
121
|
}
|
|
108
|
-
else if (
|
|
122
|
+
else if (command === 'drop') {
|
|
109
123
|
const content = parseDropArgs(args);
|
|
110
124
|
await drop(content.text, content.url);
|
|
111
125
|
}
|
|
112
|
-
else if (
|
|
126
|
+
else if (command === 'exam') {
|
|
113
127
|
const pyro = args.includes('--pyro');
|
|
114
128
|
const hacker = args.includes('--hacker');
|
|
115
129
|
await exam({ pyro, hacker });
|
|
116
130
|
}
|
|
117
|
-
else if (
|
|
131
|
+
else if (command === 'scan') {
|
|
118
132
|
await scanProfile();
|
|
119
133
|
}
|
|
120
|
-
else if (
|
|
134
|
+
else if (command === 'config') {
|
|
121
135
|
await configCommand(args);
|
|
122
136
|
}
|
|
123
|
-
else if (
|
|
137
|
+
else if (command === 'brag') {
|
|
124
138
|
const options = parseBragArgs(args);
|
|
125
139
|
await brag(options.manifestPath);
|
|
126
140
|
}
|
|
141
|
+
else if (command === 'org') {
|
|
142
|
+
await org();
|
|
143
|
+
}
|
|
144
|
+
else if (command === 'chat') {
|
|
145
|
+
await chat(args);
|
|
146
|
+
}
|
|
127
147
|
else {
|
|
128
148
|
console.error(`unknown command: ${cmd}`);
|
|
129
149
|
console.error('run hacklab --help for usage');
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const COMMANDS: readonly ["join", "login", "whoami", "sync", "drop", "exam", "scan", "config", "brag", "org", "chat"];
|
|
2
|
+
export type ResolvedCommand = {
|
|
3
|
+
kind: 'match';
|
|
4
|
+
name: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'ambiguous';
|
|
7
|
+
matches: string[];
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'unknown';
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a (possibly abbreviated) command token to a full command name by
|
|
13
|
+
* shortest unambiguous prefix:
|
|
14
|
+
* - an exact match always wins, so a full command is never shadowed by a longer
|
|
15
|
+
* one (e.g. if `scan` and `scanner` both existed, `scan` resolves to `scan`);
|
|
16
|
+
* - a prefix that matches exactly one command resolves to it (`sy` -> sync);
|
|
17
|
+
* - a prefix matching several is ambiguous (`s` -> sync | scan);
|
|
18
|
+
* - a token matching none is unknown (a typo like `ogr` does not resolve).
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveCommand(token: string, commands?: readonly string[]): ResolvedCommand;
|
|
21
|
+
//# sourceMappingURL=resolve-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-command.d.ts","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,uGAYX,CAAA;AAEV,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAA;AAEvB;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,SAAS,MAAM,EAAa,GACrC,eAAe,CAOjB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// All top-level hacklab subcommands. Used both to dispatch and to resolve a
|
|
2
|
+
// typed prefix to its full name (e.g. `sy` -> sync). Keep in sync with the
|
|
3
|
+
// dispatch chain in index.ts.
|
|
4
|
+
export const COMMANDS = [
|
|
5
|
+
'join',
|
|
6
|
+
'login',
|
|
7
|
+
'whoami',
|
|
8
|
+
'sync',
|
|
9
|
+
'drop',
|
|
10
|
+
'exam',
|
|
11
|
+
'scan',
|
|
12
|
+
'config',
|
|
13
|
+
'brag',
|
|
14
|
+
'org',
|
|
15
|
+
'chat',
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a (possibly abbreviated) command token to a full command name by
|
|
19
|
+
* shortest unambiguous prefix:
|
|
20
|
+
* - an exact match always wins, so a full command is never shadowed by a longer
|
|
21
|
+
* one (e.g. if `scan` and `scanner` both existed, `scan` resolves to `scan`);
|
|
22
|
+
* - a prefix that matches exactly one command resolves to it (`sy` -> sync);
|
|
23
|
+
* - a prefix matching several is ambiguous (`s` -> sync | scan);
|
|
24
|
+
* - a token matching none is unknown (a typo like `ogr` does not resolve).
|
|
25
|
+
*/
|
|
26
|
+
export function resolveCommand(token, commands = COMMANDS) {
|
|
27
|
+
if (commands.includes(token))
|
|
28
|
+
return { kind: 'match', name: token };
|
|
29
|
+
const matches = commands.filter((c) => c.startsWith(token));
|
|
30
|
+
if (matches.length === 1)
|
|
31
|
+
return { kind: 'match', name: matches[0] };
|
|
32
|
+
if (matches.length > 1)
|
|
33
|
+
return { kind: 'ambiguous', matches };
|
|
34
|
+
return { kind: 'unknown' };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=resolve-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-command.js","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,2EAA2E;AAC3E,8BAA8B;AAC9B,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,KAAK;IACL,MAAM;CACE,CAAA;AAOV;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,WAA8B,QAAQ;IAEtC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IAEnE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAA;IACrE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAA;IAC7D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AAC5B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const BELT_COLOR_HEX: Record<string, string>;
|
|
2
|
+
/** Unknown / missing belt falls back to the white-belt hex (matches the web). */
|
|
3
|
+
export declare const DEFAULT_ACCENT_HEX = "#E8E8E8";
|
|
4
|
+
export type Accent = {
|
|
5
|
+
solid: string;
|
|
6
|
+
alpha: (a: number) => string;
|
|
7
|
+
};
|
|
8
|
+
export declare function hexToRgb(hex: string): {
|
|
9
|
+
r: number;
|
|
10
|
+
g: number;
|
|
11
|
+
b: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The accent for a belt/rank colour: the solid hue plus an alpha() helper that
|
|
15
|
+
* reuses the original mint opacities (0.1 track, 0.18/0.38/0.62/1 heat tiers) in
|
|
16
|
+
* this hue, so only the colour changes, not the relative brightness.
|
|
17
|
+
*/
|
|
18
|
+
export declare function accentShades(beltColor: string): Accent;
|
|
19
|
+
//# sourceMappingURL=share-card-colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-card-colors.d.ts","sourceRoot":"","sources":["../src/share-card-colors.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAYjD,CAAA;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAE3C,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,CAAA;AAEpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKzE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAItD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Accent palette for the share card. The accent is the user's belt/rank colour
|
|
2
|
+
// (same hex values as the web profile's BELT_COLOR_HEX), so the card reads
|
|
3
|
+
// identically to hacklab.so/<handle>. Kept separate from share-card.tsx so it's
|
|
4
|
+
// testable without loading the satori/resvg renderer.
|
|
5
|
+
export const BELT_COLOR_HEX = {
|
|
6
|
+
white: '#E8E8E8',
|
|
7
|
+
orange: '#FF8C00',
|
|
8
|
+
red: '#DC2626',
|
|
9
|
+
blue: '#2563EB',
|
|
10
|
+
cyan: '#06B6D4',
|
|
11
|
+
yellow: '#EAB308',
|
|
12
|
+
lime: '#84CC16',
|
|
13
|
+
green: '#22C55E',
|
|
14
|
+
pink: '#EC4899',
|
|
15
|
+
purple: '#A855F7',
|
|
16
|
+
black: '#FFFFFF',
|
|
17
|
+
};
|
|
18
|
+
/** Unknown / missing belt falls back to the white-belt hex (matches the web). */
|
|
19
|
+
export const DEFAULT_ACCENT_HEX = '#E8E8E8';
|
|
20
|
+
export function hexToRgb(hex) {
|
|
21
|
+
const h = hex.replace('#', '');
|
|
22
|
+
const full = h.length === 3 ? h.replace(/(.)/g, '$1$1') : h;
|
|
23
|
+
const n = Number.parseInt(full, 16);
|
|
24
|
+
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The accent for a belt/rank colour: the solid hue plus an alpha() helper that
|
|
28
|
+
* reuses the original mint opacities (0.1 track, 0.18/0.38/0.62/1 heat tiers) in
|
|
29
|
+
* this hue, so only the colour changes, not the relative brightness.
|
|
30
|
+
*/
|
|
31
|
+
export function accentShades(beltColor) {
|
|
32
|
+
const hex = BELT_COLOR_HEX[beltColor] ?? DEFAULT_ACCENT_HEX;
|
|
33
|
+
const { r, g, b } = hexToRgb(hex);
|
|
34
|
+
return { solid: hex, alpha: (a) => `rgba(${r}, ${g}, ${b}, ${a})` };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=share-card-colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-card-colors.js","sourceRoot":"","sources":["../src/share-card-colors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,gFAAgF;AAChF,sDAAsD;AAEtD,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;IACjB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;CACjB,CAAA;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAA;AAI3C,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3D,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IACnC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAA;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,IAAI,kBAAkB,CAAA;IAC3D,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;AACrE,CAAC"}
|
package/dist/share-card.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-card.d.ts","sourceRoot":"","sources":["../src/share-card.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBlD;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvD,CAAA;
|
|
1
|
+
{"version":3,"file":"share-card.d.ts","sourceRoot":"","sources":["../src/share-card.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBlD;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvD,CAAA;AAkeD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C5E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA4C5D;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASzE"}
|
package/dist/share-card.js
CHANGED
|
@@ -5,13 +5,13 @@ import { homedir } from 'node:os';
|
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { Resvg } from '@resvg/resvg-js';
|
|
7
7
|
import satori from 'satori';
|
|
8
|
+
import { accentShades } from './share-card-colors.js';
|
|
8
9
|
// ── Design tokens (DESIGN.md) ──────────────────────────────────────────────
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
const ACCENT_TRACK = 'rgba(130,245,198,0.1)'; // unfilled bar / belt track
|
|
10
|
+
// The accent is the user's belt/rank colour (same palette as the web profile),
|
|
11
|
+
// so the card reads identically to hacklab.so/<handle>. It's the one signal
|
|
12
|
+
// colour: corner brackets, the belt + proficiency bars, and the lit heatmap
|
|
13
|
+
// cells. Everything else is neutral graphite + grey. Numbers + the nametag are
|
|
14
|
+
// Orbitron; every other glyph is JetBrains Mono.
|
|
15
15
|
const PAGE_BG = '#0B0D0C';
|
|
16
16
|
const CARD_BG = '#101513';
|
|
17
17
|
const BORDER = '#1D221F';
|
|
@@ -99,7 +99,7 @@ function buildMatrix(daily) {
|
|
|
99
99
|
return r > 0.75 ? 4 : r > 0.5 ? 3 : r > 0.25 ? 2 : 1;
|
|
100
100
|
}));
|
|
101
101
|
}
|
|
102
|
-
function Heatmap({ matrix }) {
|
|
102
|
+
function Heatmap({ matrix, accent }) {
|
|
103
103
|
return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: HEAT_GAP }, children: matrix.map((row) => (
|
|
104
104
|
// biome-ignore lint/correctness/useJsxKeyInIterable: satori has no keys
|
|
105
105
|
_jsx("div", { style: { display: 'flex', gap: HEAT_GAP }, children: row.map((tier) => tier === 0 ? (
|
|
@@ -115,29 +115,29 @@ function Heatmap({ matrix }) {
|
|
|
115
115
|
display: 'flex',
|
|
116
116
|
width: 3,
|
|
117
117
|
height: 3,
|
|
118
|
-
backgroundColor:
|
|
118
|
+
backgroundColor: accent.alpha(0.35),
|
|
119
119
|
} }) })) : (
|
|
120
120
|
// biome-ignore lint/correctness/useJsxKeyInIterable: satori has no keys
|
|
121
121
|
_jsx("div", { style: {
|
|
122
122
|
display: 'flex',
|
|
123
123
|
width: HEAT_CELL,
|
|
124
124
|
height: HEAT_CELL,
|
|
125
|
-
backgroundColor:
|
|
125
|
+
backgroundColor: accent.alpha(TIER_OPACITY[tier] ?? 0),
|
|
126
126
|
} }))) }))) }));
|
|
127
127
|
}
|
|
128
128
|
// ── Proficiency bar: solid mint fill over a 10%-mint track. ──────────────────
|
|
129
|
-
function Bar({ pct }) {
|
|
129
|
+
function Bar({ pct, accent }) {
|
|
130
130
|
const fill = Math.max(0, Math.min(100, pct));
|
|
131
131
|
return (_jsx("div", { style: {
|
|
132
132
|
display: 'flex',
|
|
133
133
|
width: 64,
|
|
134
134
|
height: 6,
|
|
135
|
-
backgroundColor:
|
|
135
|
+
backgroundColor: accent.alpha(0.1),
|
|
136
136
|
}, children: _jsx("div", { style: {
|
|
137
137
|
display: 'flex',
|
|
138
138
|
height: 6,
|
|
139
139
|
width: `${fill}%`,
|
|
140
|
-
backgroundColor:
|
|
140
|
+
backgroundColor: accent.solid,
|
|
141
141
|
} }) }));
|
|
142
142
|
}
|
|
143
143
|
function StatCard({ value, label }) {
|
|
@@ -189,7 +189,7 @@ function PillStat({ value, label }) {
|
|
|
189
189
|
color: LABEL,
|
|
190
190
|
}, children: label })] }));
|
|
191
191
|
}
|
|
192
|
-
function CornerBracket({ pos }) {
|
|
192
|
+
function CornerBracket({ pos, accent, }) {
|
|
193
193
|
const arm = 11;
|
|
194
194
|
const thick = 2;
|
|
195
195
|
const inset = 0;
|
|
@@ -202,8 +202,8 @@ function CornerBracket({ pos }) {
|
|
|
202
202
|
height: arm,
|
|
203
203
|
[vert]: inset,
|
|
204
204
|
[horiz]: inset,
|
|
205
|
-
[`border${vert === 'top' ? 'Top' : 'Bottom'}`]: `${thick}px solid ${
|
|
206
|
-
[`border${horiz === 'left' ? 'Left' : 'Right'}`]: `${thick}px solid ${
|
|
205
|
+
[`border${vert === 'top' ? 'Top' : 'Bottom'}`]: `${thick}px solid ${accent.solid}`,
|
|
206
|
+
[`border${horiz === 'left' ? 'Left' : 'Right'}`]: `${thick}px solid ${accent.solid}`,
|
|
207
207
|
} }));
|
|
208
208
|
}
|
|
209
209
|
function ShareCard({ data, matrix, avatar, }) {
|
|
@@ -212,6 +212,7 @@ function ShareCard({ data, matrix, avatar, }) {
|
|
|
212
212
|
const cost = Math.round(data.estimatedCost).toLocaleString('en-US');
|
|
213
213
|
const progress = Math.max(0, Math.min(100, data.progressPercent));
|
|
214
214
|
const initial = (data.handle[0] ?? '?').toUpperCase();
|
|
215
|
+
const accent = accentShades(data.beltColor);
|
|
215
216
|
return (_jsxs("div", { style: {
|
|
216
217
|
position: 'relative',
|
|
217
218
|
width: 800,
|
|
@@ -222,7 +223,7 @@ function ShareCard({ data, matrix, avatar, }) {
|
|
|
222
223
|
padding: 16,
|
|
223
224
|
fontFamily: 'JetBrains Mono',
|
|
224
225
|
color: WHITE,
|
|
225
|
-
}, children: [_jsx(CornerBracket, { pos: 'tl' }), _jsx(CornerBracket, { pos: 'tr' }), _jsx(CornerBracket, { pos: 'bl' }), _jsx(CornerBracket, { pos: 'br' }), _jsxs("div", { style: {
|
|
226
|
+
}, children: [_jsx(CornerBracket, { pos: 'tl', accent: accent }), _jsx(CornerBracket, { pos: 'tr', accent: accent }), _jsx(CornerBracket, { pos: 'bl', accent: accent }), _jsx(CornerBracket, { pos: 'br', accent: accent }), _jsxs("div", { style: {
|
|
226
227
|
display: 'flex',
|
|
227
228
|
height: 70,
|
|
228
229
|
alignItems: 'center',
|
|
@@ -247,7 +248,7 @@ function ShareCard({ data, matrix, avatar, }) {
|
|
|
247
248
|
fontFamily: 'Orbitron',
|
|
248
249
|
fontWeight: 700,
|
|
249
250
|
fontSize: 22,
|
|
250
|
-
color:
|
|
251
|
+
color: accent.solid,
|
|
251
252
|
}, children: initial })) }), _jsxs("div", { style: {
|
|
252
253
|
display: 'flex',
|
|
253
254
|
fontFamily: 'Orbitron',
|
|
@@ -266,12 +267,12 @@ function ShareCard({ data, matrix, avatar, }) {
|
|
|
266
267
|
display: 'flex',
|
|
267
268
|
width: 104,
|
|
268
269
|
height: 8,
|
|
269
|
-
backgroundColor:
|
|
270
|
+
backgroundColor: accent.alpha(0.1),
|
|
270
271
|
}, children: _jsx("div", { style: {
|
|
271
272
|
display: 'flex',
|
|
272
273
|
width: `${progress}%`,
|
|
273
274
|
height: 8,
|
|
274
|
-
backgroundColor:
|
|
275
|
+
backgroundColor: accent.solid,
|
|
275
276
|
} }) })] })] }), _jsxs("div", { style: { display: 'flex', height: 114, gap: 26, marginTop: 18 }, children: [_jsx(StatCard, { value: formatTokens(data.tokensTotal), label: 'TOKENS BURNED' }), _jsx(StatCard, { value: `${data.streak}D`, label: 'STREAK' }), _jsx(StatCard, { value: `$${cost}`, label: 'EST. COST' })] }), _jsxs("div", { style: { display: 'flex', height: 142, gap: 18, marginTop: 18 }, children: [_jsx("div", { style: {
|
|
276
277
|
display: 'flex',
|
|
277
278
|
width: 284,
|
|
@@ -293,14 +294,14 @@ function ShareCard({ data, matrix, avatar, }) {
|
|
|
293
294
|
fontSize: 15,
|
|
294
295
|
letterSpacing: 0.4,
|
|
295
296
|
color: LABEL_DIM,
|
|
296
|
-
}, children: shortModelName(m.name) }), _jsx(Bar, { pct: (m.tokens / modelMax) * 100 })] }))) }), _jsx("div", { style: {
|
|
297
|
+
}, children: shortModelName(m.name) }), _jsx(Bar, { pct: (m.tokens / modelMax) * 100, accent: accent })] }))) }), _jsx("div", { style: {
|
|
297
298
|
display: 'flex',
|
|
298
299
|
flex: 1,
|
|
299
300
|
alignItems: 'center',
|
|
300
301
|
justifyContent: 'center',
|
|
301
302
|
backgroundColor: CARD_BG,
|
|
302
303
|
border: `1px solid ${BORDER}`,
|
|
303
|
-
}, children: _jsx(Heatmap, { matrix: matrix }) })] }), _jsxs("div", { style: { display: 'flex', height: 42, gap: 17, marginTop: 18 }, children: [_jsx(PillStat, { value: `${data.longestStreak}D`, label: 'BEST STREAK' }), _jsx(PillStat, { value: `#${data.rank}`, label: 'RANK' }), _jsx(PillStat, { value: String(data.followers ?? 0), label: 'FOLLOWERS' })] }), _jsxs("div", { style: {
|
|
304
|
+
}, children: _jsx(Heatmap, { matrix: matrix, accent: accent }) })] }), _jsxs("div", { style: { display: 'flex', height: 42, gap: 17, marginTop: 18 }, children: [_jsx(PillStat, { value: `${data.longestStreak}D`, label: 'BEST STREAK' }), _jsx(PillStat, { value: `#${data.rank}`, label: 'RANK' }), _jsx(PillStat, { value: String(data.followers ?? 0), label: 'FOLLOWERS' })] }), _jsxs("div", { style: {
|
|
304
305
|
display: 'flex',
|
|
305
306
|
justifyContent: 'space-between',
|
|
306
307
|
marginTop: 'auto',
|